I'm using this, from here:
constructor(private heroService: HeroService,
private activatedRoute: ActivatedRoute) {
}
ngOnInit() {
const heroId = this.activatedRoute.snapshot.paramMap.get('id');
this.heroService.getHeroById(heroId).subscribe((hero: Hero) => {
...
});
}
Now I have a unit test that needs to mock this ActivatedRoute. I've already check some answers here in stackoverflow but without luck.
Notice that I'm using snapshot.paramMap so many solutions do not work at all. For example, this, this, and this do not work.
I think the near valid answer could be:
{
provide: ActivatedRoute,
useValue: {paramMap: Observable.of(convertToParamMap({id: 1}))}
}
But does not work either.
The error showing is:
Error: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'ng:///HeroesModule/HeroDetailComponent_Host.ngfactory.js'.
error properties: Object({ INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9, INUSE_ATTRIBUTE_ERR: 10, INVALID_STATE_ERR: 11, SYNTAX_ERR: 12, INVALID_MODIFICATION_ERR: 13, NAMESPACE_ERR: 14, INVALID_ACCESS_ERR: 15, VALIDATION_ERR: 16, TYPE_MISMATCH_ERR: 17, SECURITY_ERR: 18, NETWORK_ERR: 19, ABORT_ERR: 20, URL_MISMATCH_ERR: 21, QUOTA_EXCEEDED_ERR: 22, TIMEOUT_ERR: 23, INVALID_NODE_TYPE_ERR: 24, DATA_CLONE_ERR: 25, code: 19 })
This is because I'm doing a request that responses with status 500 because paramMap is undefined so there is no id on the request.
... any ideas?
Thanks and BR
It is pretty straightforward to mock the ActivatedRoute in the User component test file. All we have to do is to edit the providers list as follows: beforeEach(async(() => { TestBed. configureTestingModule({ declarations: [ UserComponent ], imports: [ RouterTestingModule, HttpClientTestingModule // ...
ActivatedRouteSnapshotlinkContains the information about a route associated with a component loaded in an outlet at a particular moment in time. ActivatedRouteSnapshot can also be used to traverse the router state tree.
Test Cases for ActivatedRoute it('getDataByNameAndID test case ', () => {route.snapshot.params.id = '2';route.snapshot.params.name = 'testParamChanged';fixture = TestBed. createComponent(MyComponent);component = fixture. componentInstance;fixture. detectChanges();expect(component.name).
ParamMaplinkA map that provides access to the required and optional parameters specific to a route. The map supports retrieving a single value with get() or multiple values with getAll() .
Add snapshot to the useValue like:
{
provide: ActivatedRoute,
useValue: {
snapshot: {
paramMap: convertToParamMap({
id: '1'
})
}
}
}
In recent Angular versions, a project's aot
setting is on by default (for better compile-time type checking). If this is the case with your project, then you probably need to at least stub out all the properties of ActivatedRoute and ActivatedRouteSnapshot. Something like this:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Type } from '@angular/core';
import { Location } from '@angular/common';
import { MockPlatformLocation } from '@angular/common/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { ActivatedRoute, ActivatedRouteSnapshot, Params, ParamMap, convertToParamMap } from '@angular/router';
import { of, BehaviorSubject } from 'rxjs';
import { HeroDetailComponent } from './hero-detail.component';
import { Hero } from '../hero';
export class MockActivatedRouteSnapshot implements ActivatedRouteSnapshot {
private innerTestParams?: Params;
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
}
get paramMap() {
return convertToParamMap(this.testParams);
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get params() {
return this.innerTestParams;
}
get queryParams() {
return this.innerTestParams;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
export class MockActivatedRoute implements ActivatedRoute {
private innerTestParams?: Params;
private subject?: BehaviorSubject<Params> = new BehaviorSubject(this.testParams);
private paramMapSubject?: BehaviorSubject<ParamMap> = new BehaviorSubject(convertToParamMap(this.testParams));
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
this.subject.next(params);
this.paramMapSubject.next(convertToParamMap(params));
}
get snapshot() {
return new MockActivatedRouteSnapshot(this.testParams);
}
get params() {
return this.subject.asObservable();
}
get queryParams() {
return this.params;
}
get paramMap() {
return this.paramMapSubject.asObservable();
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
describe('HeroDetailComponent', () => {
let component: HeroDetailComponent;
let fixture: ComponentFixture<HeroDetailComponent>;
let httpMock: HttpTestingController;
let routeMock: MockActivatedRoute;
let initialMockParams: Params;
let locationMock: MockPlatformLocation;
beforeEach(async(() => {
initialMockParams = {id: 11};
routeMock = new MockActivatedRoute(initialMockParams);
locationMock = new MockPlatformLocation;
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
],
declarations: [ HeroDetailComponent ],
providers: [
{
provide: ActivatedRoute, useValue: routeMock,
},
{
provide: Location, useValue: locationMock,
}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeroDetailComponent);
component = fixture.componentInstance;
httpMock = TestBed.inject<HttpTestingController>(HttpTestingController as Type<HttpTestingController>);
fixture.detectChanges();
});
afterEach(() => {
httpMock.verify();
});
it('should be created', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
const dummyHero: Hero = { id: 11, name: 'dummyHero' };
const req = httpMock.expectOne('api/details/11');
req.flush(dummyHero);
});
});
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