问题
I'm working on building out tests for my services in Angular 2. Building out the mock backends is proving to be a real trial. I have been able to test the services with it making actual HTTP requests successfully but I would like to keep these segregated from the third part.
I've combed through the two main articles I have been able to find (first, second as well as the angular docs.
When I was making successful http requests to actual third party services, I had to use done();
to ensure that the test waited for the request to complete. It seems that the case is the same here. If I do not use it, the test will be a success even with expect(1).toBe(2);
. When I do use it, it times out waiting for the call to complete. Error:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
Here's my code:
import {
it,
inject,
describe,
beforeEachProviders,
expect,
} from '@angular/core/testing';
import { BaseRequestOptions, Response, ResponseOptions, Http } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { AccountService } from './../../source/scripts/services/account.service';
import { provide } from '@angular/core';
describe('AccountService', () => {
// let service;
beforeEachProviders(() => [
AccountService,
BaseRequestOptions,
MockBackend,
provide(Http, {
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
},
}),
]);
beforeEach(<any>inject([MockBackend], (backend: MockBackend) => {
const baseResponse = new Response(new ResponseOptions({ body: 'got response' }));
backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
}));
// We use 'done' for async callbacks (http calls)
it('should return mocked response', (done) => {
inject([AccountService], (testService: AccountService) => {
testService.getUsers().subscribe((res: Response) => {
expect(res.text()).toBe('got response');
expect(1).toBe(2);
done();
});
});
});
});
How do I properly test http calls with a mockbackend? I suspect that either the links I referenced above are out of date or they didn't confirm that the test was actually testing rather than just giving false positives without the async of done();
.
回答1:
You were very close. Only the async done
is not appropriate here because inject
has to replace this anonymous callback. So here is the fixed version:
it('should return mocked response', inject([AccountService], (testService: AccountService) => {
testService.getUsers().subscribe((res: Response) => {
expect(res.text()).toBe('got response');
expect(1).toBe(2);
});
}));
Another problem is missing beforeEach
import:
import {
it,
inject,
describe,
beforeEach, // <-- this one was missing
beforeEachProviders,
expect,
} from '@angular/core/testing';
So there was a Jasmine's beforeEach
instance which doesn't allow to use inject
.
来源:https://stackoverflow.com/questions/37734760/testing-http-with-mockbackends