I am using Angular version "4.2.2", Angular Cli version "1.1.1" and zone.js 0.8.12. Some of my unit tests that used to work either in Chrome and PhanthomJS are now failing with the following error:
ERROR Uncaught Error: macroTask 'setInterval': can not transition to 'running', expecting state 'scheduled', was 'notScheduled'.
Anyone has seen these errors before and know how to fix them?
Ok, so after a bit of research, I've found that most people (even the Angular people), say themselves that using async
or fakeAsync
with code that involves the intervalTimer
(common with Observable methods) simply cannot be done.
Where I found this was at this link
For example, I was testing an observable method with the fakeAsync
and tick
technique spelled out in the Angular2 docs and was running into this error. (see test below)
it('#findCaseMasks should show error if error is returned from service', fakeAsync(() => {
component.searchCriteria = new CaseMaskModel(1, 1);
caseMaskServiceSpy = spyOn(service, 'findCaseMasks').and.returnValue(Observable.throw('error occured', Scheduler.async));
component.findCaseMasks();
expect(component.error).toBeNull;
tick();
fixture.detectChanges();
expect(component.error).toEqual('Something went wrong. Please contact helpdesk if the issue persists.');
}));
The test above was changed to what you see below and the test began working fine.
it('#findCaseMasks should show error if error is returned from service', (done) => {
component.searchCriteria = new CaseMaskModel(1, 1);
caseMaskServiceSpy = spyOn(service, 'findCaseMasks').and.returnValue(Observable.throw('error occured', Scheduler.async));
component.findCaseMasks();
expect(component.error).toBeNull;
caseMaskServiceSpy.calls.mostRecent().returnValue.subscribe(
() => { //success
//put code here if testing for success
},
err => { //error
//put code here if testing for error
fixture.detectChanges();
expect(component.error).toEqual('Something went wrong. Please contact helpdesk if the issue persists.');
done();
});
});
So basically you have to spy on the service that was injected into the component with `jasmine.Spy' and then subscribe to its most recent calls. Then you have familiar subscription syntax in order to check for errors and to check for success.
For reference, the steps to spy on the injected service are as follows:
describe
method that is of the same type of the service that you're trying to spy, ie. let casemaskService: CaseMaskService;
describe
method that is of the type jasmine.Spy
, ie let casemaskServiceSpy: jasmine.Spy;
fixture
's injected service of the same type, ie casemaskService = fixture.debugElement.injector.get(CaseMaskService);
. (I usually do this in the synchronous beforeEach
method)spy
variable equal to a spyOn
instance and tell it what to return, ie caseMaskSpy = spyOn(casemaskService, 'updateCaseMask').and.returnValue(Observable.of(
${mockCaseMask.caseMaskingId} was updated!, Scheduler.async));
At that point you can use the code I've pasted above and should be good to go.
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