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?
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?
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 .
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With