At 51zero, we love Angular for creating web-apps for our clients. With Angular 2.0 now firmly in Beta and stabilised, its the perfect time to show you how we're testing in Angular 2.0.
The key concept which we apply in all tests is to stub / spy on all external dependencies and the methods called within the unit itself. A small exception would be static methods from generic libraries e.g. Array.forEach, underscorejs etc, which do not hold state.
All of the private methods (even they are exposed as public when transpiled to js, and not truly private) should be tested strictly via the public methods/ events only. In such cases they could be either stubbed e.g. to simplify the result or mock the behaviour of them.
Angular provides a great way to do so easily with the dependency injection at the core of its framework.
Angular2 has got three types of concepts, which require slightly different setup of tests and logic of testing - Components, Pipes and Services.
The easiest of all is Pipes, as they behave as/are essentially static methods.
First of all lets define the important bits in karma.conf.js file:
here src/vendors.ts contains the import statements for all vendor dependencies e.g.
The pipe under test
The test here can be simply done without involving the angular injector - which makes the code framework agnostic.
The import statements can also be excluded, as they are just wrapper for the global.it, global.describe, etc. Injected by jasmine into the global object.
Not much of an advantage here except perhaps some of the jasmine.d.ts definitions come for free.
So the following works (which can be ported to any framework as it is ECMA6 compliant after stripping types from typescript if any):
or alternatively (not my preferred approach) the pipe can be tested within the context of a template - e.g. testing it's selector
Lets define the service:
and the simplest test with stubbing Http with another class to match the same name and methods used in the class under test
An alternative way of doing it - by using the angular2 injector instead and spy on the methods used within the class under test.
Component can be tested in a few ways
- As a normal typescript / ECMA6 class, without involving angular injector (which may not suit all components - e.g. stubbing all the dependencies may become a more tedious task, compared to leaving the injector to do the wiring).
- As a normal typescript / ECMA6 class, but with the addition of the injector and/or provider - then getting an instance of the component, created by angular. It is my preferred approach. It would usually involve stubbing the template to avoid http request calls.
- Testing the actual dom generated by the template from the component, events, expected behavior etc.
Lets define the component
Testing without angular2 injector involved
Testing with the injector but without involving the template
Testing with compiling the template
There are also more scenarios which are not covered here (e.g. testing zone.js / http provider with using mocking provider etc)
Let us know in the comments below your thoughts on Angular2 and its implementation.
Further reading: Angular Testing