Reputation: 3868
When trying to test a component with routeParams or router in the constructor one gets error:
No provider for RouteParams
Here is my component example:
@Component({
selector: 'memory',
template: '',
})
export class TestedComponent {
constructor(
private _someService: SomeService,
private _routeParams: RouteParams,
private _router: Router
) {
this.whatever = this._someService.find(this._routeParams.get('id'));
}
}
It took me a lot of time to find this solution, and I would like to share it!
Upvotes: 1
Views: 1186
Reputation: 3868
So we need to mock the router. I have created a separate file called mockRouter.ts:
import {provide} from 'angular2/core';
import {
Location,
LocationStrategy,
ComponentInstruction,
Router,
RouteParams
} from 'angular2/router';
import {ResolvedInstruction} from 'angular2/src/router/instruction';
import {SpyObject} from 'angular2/testing_internal';
export class MockRouteParams extends SpyObject {
private ROUTE_PARAMS = {};
constructor() { super(RouteParams); }
set(key: string, value: string) {
this.ROUTE_PARAMS[key] = value;
}
get(key: string) {
return this.ROUTE_PARAMS[key];
}
}
export class MockRouter extends SpyObject {
constructor() { super(Router); }
isRouteActive(s) { return true; }
generate(s) {
return new ResolvedInstruction(new ComponentInstruction('detail', [], null, null, true, '0'), null, {});
}
}
export class MockLocationStrategy extends SpyObject {
constructor() { super(LocationStrategy); }
}
export class MockLocation extends SpyObject {
constructor() { super(Location); }
}
export class MockRouterProvider {
mockRouter: MockRouter = new MockRouter();
mockRouteParams: MockRouteParams = new MockRouteParams();
mockLocationStrategy: MockLocationStrategy = new MockLocationStrategy();
mockLocation: MockLocation = new MockLocation();
setRouteParam(key: string, value: any) {
this.mockRouteParams.set(key, value);
}
getProviders(): Array<any> {
return [
provide(Router, {useValue: this.mockRouter}),
provide(RouteParams, {useValue: this.mockRouteParams}),
provide(Location, {useValue: this.mockLocation}),
provide(LocationStrategy, {useValue: this.mockLocationStrategy})
];
}
}
Then in my tests I did:
import{MockRouterProvider} from '../services/specs/mockRouter';
describe('Tested component', () => {
let mockRouterProvider = new MockRouterProvider();
beforeEachProviders(() => [
TestedComponent,
...all others,
HTTP_PROVIDERS,
mockRouterProvider.getProviders(),
]);
let tcb: TestComponentBuilder;
beforeEach(
inject(
[TestComponentBuilder, FakerService], (...injectables) => {
[tcb] = injectables;
}
)
);
it('should render',
injectAsync([], () => {
mockRouterProvider.setRouteParam('id', '1');
return tcb.createAsync(MemoryComponent)
.then((componentFixture) => {
componentFixture.detectChanges();
let compiled = componentFixture.nativeElement;
expect(compiled.firstChild).toHaveCssClass('tested-wrapper');
componentFixture.destroy();
}).catch((e) => {
expect(true).toBeFalsy(`Error: ${e.message}`);
});
})
);
Hope this helps out!
Upvotes: 1