Reputation: 9682
I have an Angular service, generated through Swagger.
The service just makes an HTTP call and return a list of Users. I managed to properly code tests case for "success" calls.
However, I struggle making the test for "fail" cases.
I tried to simply call the function and by Mocking a response, creating an "errored" response, but it doesn't seem to be able to detect an Exception was actually thrown.
Below you will find both the Service and my test case:
getListUsers(): Observable<UsersListModel | null> {
let url_ = this.baseUrl + "/api/users";
url_ = url_.replace(/[?&]$/, "");
const content_ = "";
let options_ = {
body: content_,
method: "get",
headers: new Headers({
"Content-Type": "application/json; charset=UTF-8",
"Accept": "application/json; charset=UTF-8"
})
};
return this.http.request(url_, options_).flatMap((response_) => {
return this.processGetListUsers(response_);
}).catch((response_: any) => {
if (response_ instanceof Response) {
try {
return this.processGetListActivities(response_);
} catch (e) {
return <Observable<UsersListModel>><any>Observable.throw(e);
}
} else
return <Observable<UsersListModel>><any>Observable.throw(response_);
});
}
protected processGetListUsers(response: Response): Observable<UsersListModel | null> {
const status = response.status;
if (status === 200) {
const responseText = response.text();
let result200: UsersListModel | null = null;
let resultData200 = responseText === "" ? null : JSON.parse(responseText, this.jsonParseReviver);
result200 = resultData200 ? UsersListModel.fromJS(resultData200) : <any>null;
return Observable.of(result200);
} else if (status !== 200 && status !== 204) {
const responseText = response.text();
return throwException("An unexpected server error occurred.", status, responseText);
}
return Observable.of<UsersListModel | null>(<any>null);
}
describe('ERROR on Get Users List', () => {
let backend: MockBackend;
let service: UserService;
let response: Response;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [
MockBackend,
{ provide: XHRBackend, useClass: MockBackend },
UserService
]
});
}));
beforeEach(inject([Http, XHRBackend], (http: Http, be: MockBackend) => {
backend = be;
service = new UserService(http);
let options = new ResponseOptions({status: 500, body: 'API Error'});
response = new Response(options);
}));
it('should handle an API error on getListUsers()', async(inject([], () => {
backend.connections.subscribe((c: MockConnection) => {
c.mockRespond(response);
});
expect(() => service.getListUsers()).toThrowError();
}))
);
});
With this test case, the test fails without more information:
Expected function to throw an Error.
I even tried to use the subscription to detect something:
it('should handle an API error on getListUsers()', async(inject([], () => {
backend.connections.subscribe((c: MockConnection) => {
c.mockRespond(response);
});
spyOn(console, 'error');
service.getListUsers()
.subscribe(
res => {},
err => {
console.error(err)
});
expect(console.error).toHaveBeenCalled();
}))
);
Here I can see the error thrown in console, but the console.error is never triggered.
So, maybe my test case is not appropriate.
Upvotes: 2
Views: 2551
Reputation: 31873
That assertion helper isn't going to work because the error gets wrapped and propagated through the Observable's error notification channel.
For this to work you need to subscribe to the observable and assert accordingly
service.getListActivities().subscribe(
() => test.failure('expected an error but observable terminated successfully.'),
() => test.success('observable threw an error as expected.')
);
The example is generalized as the specific helpers that you call will depend on the test framework in use.
Upvotes: 1