angular
angular copied to clipboard
Clarify how to test for errors in effects
Describe the problem that you experienced
Given a component that has an effect that throws an error, it's not clear what is the correct way to write a unit test to test for that error. Please see the code below. This is a standard way to test that something throwing an error. However, this unit test does not pass saying that exception was not thrown. Notably, the expected thrown error is visible in the terminal.
class MyComponent {
name = input.required<string>();
private validateNameEffect = effect(() => {
if (this.name() !== 'Tom') {
throw new Error('Not Tom')
}
});
}
it('should throw error', () => {
expect(() => {
const fixture = TestBed.configureTestingModule({
imports: [MyComponent],
}).createComponent(MyComponent);
fixture.detectChanges();
TestBed.flushEffects();
}).toThrow()
});
I figured out a way to make test pass using custom ErrorHandler
. However, that seems very hacky:
class TestErrorHandler extends ErrorHandler {
caughtError: any;
override handleError(error: any) {
this.caughtError = error;
// not calling original error handling to avoid
// terminal being polluted
// super.handleError(error);
}
}
it('should throw error', () => {
const fixture = TestBed.configureTestingModule({
imports: [MyComponent],
providers: [
{ provide: ErrorHandler, useClass: TestErrorHandler },
],
}).createComponent(MyComponent);
const errorHandler = TestBed.inject(ErrorHandler) as unknown as TestErrorHandler;
expect(errorHandler.caughtError).toBeDefined();
});
Enter the URL of the topic with the problem
https://twitter.com/dmitryaefimenko/status/1788714569420173689
Describe what you were looking for in the documentation
Clear instructions on how to test for errors in effects
Describe the actions that led you to experience the problem
No response
Describe what you want to experience that would fix the problem
No response
Add a screenshot if that helps illustrate the problem
No response
If this problem caused an exception or error, please paste it here
No response
If the problem is browser-specific, please specify the device, OS, browser, and version
No response
Provide any additional information here in as much as detail as you can
No response
Context:
https://github.com/angular/angular/blob/28fb385eec03f64b624a9b67d6d8147b6872a939/packages/core/src/render3/reactivity/effect.ts#L175-L182
Effects do log their error to the error handler, so you're on correct path.
You could just spy the handleError
method for example:
test('should throw error', () => {
const fixture = TestBed.configureTestingModule({
imports: [MyComponent],
}).createComponent(MyComponent);
const errorHandler = TestBed.inject(ErrorHandler);
const spy = vi.spyOn(errorHandler, 'handleError');
fixture.detectChanges();
expect(spy).toBeCalledWith(new Error('foobar'));
});
https://stackblitz.com/edit/angular-vitest-starter-v18-ryiakv
sounds good, thanks for the clarification. Do you think this should be mentioned somewhere in the docs?