How to unit test a Angular 4 component which uses router.paramMap
For anyone needing tests on a component for when it does have a certain route param, and when it does not have it (as in /product
and /product/:id
), the following works for me:
The component:
export class PageProductComponent implements OnInit {
id: string | null = null;
constructor(private readonly activatedRoute: ActivatedRoute) { }
ngOnInit(): void {
this.id = this.activatedRoute.snapshot.paramMap.get('id');
}
}
The tests:
describe('PageProductComponent ', () => {
let component: PageProductComponent ;
let fixture: ComponentFixture<PageProductComponent >;
let debugEl: DebugElement;
const makeCompiledTestBed = (provider?: object): void => {
const moduleDef: TestModuleMetadata = {
imports: [
RouterTestingModule,
],
declarations: [ PageProductComponent ],
providers: [ ]
};
if (moduleDef.providers && provider) {
moduleDef.providers.push(provider);
}
TestBed.configureTestingModule(moduleDef).compileComponents();
};
const setupTestVars = (): void => {
fixture = TestBed.createComponent(PageProductComponent );
component = fixture.componentInstance;
debugEl = fixture.debugElement;
fixture.detectChanges();
};
describe('When an ID is NOT provided in the URL param', () => {
beforeEach(async(makeCompiledTestBed));
beforeEach(setupTestVars);
it('should list all products', () => {
//...
});
});
describe('When an ID is provided in the URL param', () => {
beforeEach(async(() => {
makeCompiledTestBed({
provide: ActivatedRoute,
useValue: {
snapshot: {
paramMap: convertToParamMap({id: 1234})
}
}
});
}));
beforeEach(setupTestVars);
it('should show a specific product', () => {
//...
});
});
});
You need to provide paramMap
instead of params
. paramMap
should be of type ParamMap
from @angular/router
, so normal object can be converted to ParamMap
using the method convertToParamMap()
from @angular/routing
.
You can provide the mock ActivatedRoute like below:
import { convertToParamMap} from '@angular/router';
....
.....
{
provide: ActivatedRoute,
useValue: { paramMap: Observable.of(convertToParamMap({id: 1})) }
}
I am using a slightly different method of getting the params in my component:
this.id = this.route.snapshot.paramMap.get('id');
And this is what worked for me in the jasmine test:
{
provide: ActivatedRoute,
useValue: {
snapshot: {
paramMap: convertToParamMap({id: 1})
}
}
}