Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing socket.io in Angular

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?

like image 733
George Edwards Avatar asked Jun 20 '17 14:06

George Edwards


People also ask

How is unit testing done in Angular?

To run the test, you will only need to run the command ng test . This command will also open Chrome and run the test in watch mode, which means your test will get automatically compiled whenever you save your file. In your Angular project, you create a component with the command ng generate component doctor .

Does Angular have unit testing?

Angular Unit testing is the process of testing small and isolated pieces of code in your Angular application. This provides an added advantage to the users in the sense that they can add any new features without breaking any other part of their application.

What is unit testing with example Angular?

Unit tests are written using Jasmine and are run to see if individual parts of an application are working correctly. As a result, unit tests will either pass or fail depending on if the code is working correctly or has a bug. Angular uses Karma as the test runner for the project's unit tests.


1 Answers

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.

like image 179
JuanGG Avatar answered Oct 05 '22 09:10

JuanGG