17

I am trying to unit test an angular service in my application, which creates socket.io client. My service looks something like this:

export class SocketService {
  private name: string;
  private host: string = window.location.protocol + "//" + window.location.hostname + ":3000";
  socket: io.Socket;

  constructor() { }

  subscribeEvent(name: string): Observable<IJobResp> {
    this.setup(name);
    return new Observable(observer => {
      this.socket.on('job', val => observer.next(val))
    })
  }

  private setup(name: string) {
    this.name = name;
    let socketUrl = this.host + "/" + this.name;
    this.socket = io.connect(socketUrl);
  }
}

So to write my test, I am using the mock-socket library to set up a mock socket.io server. Here is what the test looks like:

describe('SocketService', () => {
  let socket;

  const mockServer = new Server('http://localhost:3000/');
  mockServer.on('connection', server => {
    mockServer.emit('job', 'test message 1');
  });

  (window as any).io = SocketIO;
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [JobService]
    });
  });

  it('should xyz, inject([JobService], fakeAsync((service: JobService) => {
    service.subscribeEvent('/').subscribe(val => {
      expect(val).toEqual('test message 1');
    })
  })));
});

However, that test throws the error:

Error: Cannot make XHRs from within a fake async test.

If I don't have the fakeAsync, then the test passes before the assertion in the subscribe() is processed.

How do I get around this?

Update:

Another approach I have tried is to use async e.g.

  it('should subscribe to dwnTime events', async(inject([JobService], (service: JobService) => {
    service.subscribeEvent('line/602').subscribe(val => {
      expect(val).toEqual('test 2');
    })
  })));

Then I get:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

This looks like a timing issue, but I still am not sure why?

1
  • It would be easier to test your service if it did not refer to globals. Why not inject io or at least import it so that something can replace it? Commented Nov 5, 2017 at 0:23

1 Answer 1

2

Your second approach is the right one as the mock server is a real one, therefore you need to increase the timeout by setting

jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; (the value is to be adjusted)

anywhere inside the describe function.

Here you can find a full example.

Sign up to request clarification or add additional context in comments.

1 Comment

Link is broken.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.