I'm trying to write unit tests for the actions performed by our Angular application through ngxs. In one of my tests, I'm expecting the action to throw an Error. I tried using
expect(function() {store.dispatch(new MyAction(param));}).toThrowError();
but it gives me the message "Expected function to throw an Error." even though I see the Error in my console. After this failure I tried the following:
let errorMessage;
try {
store.dispatch(new MyAction(param));
} catch (error) {
console.log("In catch!");
errorMessage = error;
}
expect(errorMessage).toBe(myErrorMessage);
Once again I see the Error in my console, but I don't see the "In catch!" console.log in my catch clause. After some research I found out that angular has it's own ErrorHandler, which catches this Error before jasmine can do something with it. How can you prevent this?
The answer is: mock the angular ErrorHandler using jasmine! First create a spy:
export const errorHandlerSpy = () => jasmine.createSpyObj('ErrorHandler', {
handleError: undefined
});
use this spy as a provider in your tests:
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [NgxsModule, /*other imports*/],
providers: [
{ provide: ErrorHandler, useFactory: errorHandlerSpy }
]
}).compileComponents();
}));
check for thrown Errors like this:
const errorHandler = TestBed.get(ErrorHandler);
store.dispatch(new MyAction(param));
expect(errorHandler.handleError).toHaveBeenCalledWith(new Error('Your error message'));
I hope I saved someone else the headache of figuring this out!