Testing Services
- a service without dependencies can be instantiated like a pipe and then the logic can be tested
- especially services including HTTP calls are interesting
- Angular offers the so called in-memory-web-api-module for this
- Very new, hence relatively bad documentation
- Original MockBackend method was deprecated.
Dependency Injection in Tests
- can be done in a beforeEach block
- using the async function
- it expects as parameter an Array of dependencies and a function to which the instances are passed
- They have to be registered as providers in the testing module
beforeEach(inject([myService, MockBackend],
(myService, mockBackend) => {
service = myService;
backend = mockBackend;
}));
Usage of the MockBackend
- we instantiate the Http provider using the MockBackend and the BaseRequestOptions
- with useFactory we signal, that we provide a factory method to instantiate the provider
- Important here is the MockBackend: It allows us to check connections and reply with mocked replies
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [VisitorService, MockBackend,
BaseRequestOptions,
{
provide: Http,
useFactory: (backend, defaultOptions) =>
new Http(backend, defaultOptions),
deps: [MockBackend, BaseRequestOptions]
}
]
});
});
HTTP Method and URL Assertion
backend.connections.subscribe(connection => {
expect(connection.request.url).toBe('api/visitors');
expect(connection.request.method)
.toEqual(RequestMethod.Get);
});
Defining a Mock Reply
backend.connections.subscribe(connection => {
let responseOptions = new ResponseOptions(
{
body: mockResponse
}
);
connection.mockRespond(new Response(responseOptions));
});
calling the service and checking the result
it('should get the Visitors as an Observable', () => {
service.getAllVisitors().subscribe(visitors => {
expect(visitors.length).toBe(1);
expect(visitors[0].firstName).toEqual('Petra');
});
});
Everything in Action
- See branch 12_Testing_4
- in the file src/app/cinema/visitors/visitor.service.spec.ts
- Important: Most of the testing API's have the status @Experimental
- From my point of view, there's still much room for improvement regarding the testing API's
- many common use cases could be covered in a simpler way
Simplification Example
const mockedHttpProvider: FactoryProvider = {
provide: Http,
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: MockBackend,
defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [
VisitorService,
MockBackend,
BaseRequestOptions,
mockedHttpProvider
]
});
});