Async error
If and when returning mocked error from the testing service or in tests, users should avoid doing something like this:
public getData(data: TData): Observable<TData>{
if(!data){
return of(throwError(new HttpErrorResponse({ error: { message: 'The data cannot be found' }, status: 404 })));
}
...
}
or
describe('synchronous error throwing', () => {
...
it('should return not found error if data does not exist', () => {
spyOn(mockService, 'mockMethod').and.returnValue(of(new HttpErrorResponse({ error: { message: 'The data cannot be found' }, status: 404 })));
);
});
});
The examples above throw observable errors but it returns them synchronously. This isn't how services that make API calls behave in real world applications.
The purpose of creating test doubles for services or simulating async behavior directly in test suits is to mock the behavior of real world services as closely as possible. This can can be achieved in multiple ways.
This specific implementation uses observeOn
operator with asyncScheduler
, creating a new macrotask that places the observable in the event loop queue.
1. Usage
When returning the mocked error in test suites or test doubles, simply wrap the error data using asyncError
function and the error will be returned asynchronously.
1.1. Test double scenario
export class MockedDataFetchingService {
public getSomeData(data: TData): Observable<TData> {
return data
? asyncData(data)
: asyncError(new HttpErrorResponse({ error: { message: 'The data cannot be found' }, status: 404 }));
}
}
1.2. Test suite scenario
describe('asyncError demo', () => {
...
it('should return not found error if data does not exist', () => {
spyOn(mockService, 'mockMethod').and.returnValue(
asyncError(new HttpErrorResponse({ error: { message: 'The data cannot be found' }, status: 404 }))
);
});
});