How do I unit test routers in Angular version 2.0.0 with karma and jasmine?
Here's what my old unit test looks like in version 2.0.0-beta.14
import {
it,
inject,
injectAsync,
beforeEach,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';
import { RootRouter } from 'angular2/src/router/router';
import { Location, RouteParams, Router, RouteRegistry, ROUTER_PRIMARY_COMPONENT } from 'angular2/router';
import { SpyLocation } from 'angular2/src/mock/location_mock';
import { provide } from 'angular2/core';
import { App } from './app';
describe('Router', () => {
let location, router;
beforeEachProviders(() => [
RouteRegistry,
provide(Location, {useClass: SpyLocation}),
provide(Router, {useClass: RootRouter}),
provide(ROUTER_PRIMARY_COMPONENT, {useValue: App})
]);
beforeEach(inject([Router, Location], (_router, _location) => {
router = _router;
location = _location;
}));
it('Should be able to navigate to Home', done => {
router.navigate(['Home']).then(() => {
expect(location.path()).toBe('');
done();
}).catch(e => done.fail(e));
});
});
Instead of using
useValue
forrouterStub
, you can useuseClass
in theproviders
and it really worked for me.And in the
beforeEach
just instantiate therouterStub
object likeAnd in the test cases
Good approach suggested by Paul I have also configure my routing same way but additionally I have added service to update some data for routing and then check for current location.
so you can add service to update data on component which render some data and then will check about navigation.
configure below in TestBed.configureTestingModule
then create get service in foreach
update some data from service like
This way you can play after some data rendering happen.
For testing we now create a testing module using
TestBed
. We can use theTestBed#configureTestingModule
and pass a metadata object to it the same way we would pass to@NgModule
For routing, instead of using the normal
RouterModule
, we would instead useRouterTestingModule
. This sets up theRouter
andLocation
, so you don't need to yourself. You can also pass routes to it, by callingRouterTestingModule.withRoutes(Routes)
To get the
Location
andRouter
in the test, the same thing works, as in your example.You could also inject into each test as necessary
The
async
above is used likedone
except we don't need to explicitly calldone
. Angular will actually do that for us after all asynchronous tasks are complete.Another way to get the providers is from the test bed.
Here's a complete test, refactoring your example
UPDATE
Also, if you want to simply mock the router, which actually might be the better way to go in a unit test, you could simply do
And in your tests, all you want to do is test that the stub is called with the correct argument, when the component interacts with it
Unless you actually want to test some routing, this is probably the preferred way to go. No need to set up any routing. In a unit test, if you are using real routing, you're involving unnecessary side effects that could affect what you are really trying to test, which is just the behavior of the component. And the behavior of the component is to simply call the
navigate
method. It doesn't need to test that the router works. Angular already guarantees that.