I am having some trouble injecting a mock for a RouteParams dependency in a test for an Angular2 component. My general thought is that I might be missing some providers.
The tests fail with:
Cannot resolve all parameters for 'RouteParams'(?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'RouteParams' is decorated with Injectable.
Does anyone know what the issue might be?
import {
it,
inject,
injectAsync,
describe,
beforeEach,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';
import {Component, provide} from 'angular2/core';
import {BaseRequestOptions, Http} from 'angular2/http';
import {MockBackend} from 'angular2/http/testing';
import {RouteParams, ROUTER_PROVIDERS, ROUTER_PRIMARY_COMPONENT} from 'angular2/router';
// Load the implementations that should be tested
import {Home} from './home';
import {Title} from './providers/title';
describe('Home', () => {
// provide our implementations or mocks to the dependency injector
beforeEachProviders(() => [
Title,
Home,
provide(RouteParams, { useValue: new RouteParams({ id: '1' }) }),
BaseRequestOptions,
MockBackend,
provide(Http, {
useFactory: function(backend, defaultOptions) {
return new Http(backend, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]
}),
provide(RouteParams, {
useFactory: function() {
return new RouteParams({ 'id':'1' });
}
})
]);
it('should have a title', inject([ Home ], (home) => {
expect(home.title.value).toEqual('Angular 2');
}));
it('should have a http', inject([ Home ], (home) => {
expect(!!home.http).toEqual(true);
}));
it('should log ngOnInit', inject([ Home ], (home) => {
spyOn(console, 'log');
spyOn(console, 'info');
expect(console.log).not.toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
home.ngOnInit();
expect(console.log).toHaveBeenCalled();
expect(console.info).toHaveBeenCalledWith('1');
}));
});
Managed to solve this myself, you mock RouteProvider by using
provide(RouteParams, { useValue: new RouteParams({ id: '1' }) })
import {
it,
inject,
injectAsync,
describe,
beforeEach,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';
import {Component, provide} from 'angular2/core';
import {BaseRequestOptions, Http} from 'angular2/http';
import {MockBackend} from 'angular2/http/testing';
import {RouteParams, ROUTER_PROVIDERS, ROUTER_PRIMARY_COMPONENT} from 'angular2/router';
// Load the implementations that should be tested
import {Home} from './home';
import {Title} from './providers/title';
describe('Home', () => {
// provide our implementations or mocks to the dependency injector
beforeEachProviders(() => [
Title,
Home,
provide(RouteParams, { useValue: new RouteParams({ id: '1' }) }),
BaseRequestOptions,
MockBackend,
provide(Http, {
useFactory: function(backend, defaultOptions) {
return new Http(backend, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]
})
]);
it('should have a title', inject([ Home ], (home) => {
expect(home.title.value).toEqual('Angular 2');
}));
it('should have a http', inject([ Home ], (home) => {
expect(!!home.http).toEqual(true);
}));
it('should log ngOnInit', inject([ Home ], (home) => {
spyOn(console, 'log');
spyOn(console, 'info');
expect(console.log).not.toHaveBeenCalled();
expect(console.info).not.toHaveBeenCalled();
home.ngOnInit();
expect(console.log).toHaveBeenCalled();
expect(console.info).toHaveBeenCalledWith('1');
}));
});
For people who land here even though they are working with Angular4
I just went ahead and created a mock. I guess the trick is to mock the parts of the ActivatedRoute
you need. for me this did it:
import {ActivatedRoute, ParamMap} from '@angular/router';
/**
* Mocking the ActivatedRoute which is injected in the Component on creation.
* This allows for easier testing as values can be set as needed.
*/
class MockActivatedRoute {
paramMap = Observable.of(new Params());
}
/**
* Bare bones implementation of ParamMap used in mock. Further tests can expand
* on this implementation as needed.
*/
class Params implements ParamMap {
keys: string[];
private routes: {[key: string]: string|null} = {
subject: 'foo',
time: 'd-123-1',
device: 'all',
location: 'c-123'
};
constructor() {
this.keys = Object.keys(this.routes);
}
has(name: string): boolean {
throw new Error('Method not implemented.');
}
get(name: string): string|null {
return this.routes[name];
}
getAll(name: string): string[] {
throw new Error('Method not implemented.');
}
}
And then make sure in your testing module you provide the mocked service over the real ActivatedRoute
:
providers: [
{
provide: ActivatedRoute,
useValue: new MockActivatedRoute(),
}
]
For completion, the way I use it in the Component I'm testing:
ngOnInit() {
this.route.paramMap
.map((params: ParamMap) => params.get('subject') as string)
.subscribe((subject: string) => this.subject = subject);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With