Comment se moquer d'une Route parent activatedRoute dans angular2 à des fins de test?
Disons que j'ai ceci
export class QuestionnaireQuestionsComponent {
questions: Question[] = [];
private loading:boolean = true;
constructor(
private route: ActivatedRoute,
public questionnaireService:QuestionnaireService) {}
ngOnInit(){
this.route.parent.params.subscribe((params:any)=>{
this.questionnaireService.getQuestionsForQuestionnaire(params.id).subscribe((questions)=>{
this.questions = questions;
this.loading = false;
});
});
}
}
Mon composant fonctionne plutôt bien. Le problème est que je veux le tester mais je ne peux pas comprendre comment se moquer de l'objet this.route.parent
. Voici mon test qui échoue
beforeEach(()=>{
route = new ActivatedRoute();
route.parent.params = Observable.of({id:"testId"});
questionnaireService = jasmine.createSpyObj('QuestionnaireService', ['getQuestionsForQuestionnaire']);
questionnaireService.getQuestionsForQuestionnaire.and.callFake(() => Observable.of(undefined));
component = new QuestionnaireQuestionsComponent(route, questionnaireService);
});
describe("on init", ()=>{
it("must call the service get questions for questionnaire",()=>{
component.ngOnInit();
expect(questionnaireService.getQuestionsForQuestionnaire).toHaveBeenCalled();
});
});
Le test échoue avec cette erreur
TypeError: undefined is not an object (evaluating 'this._routerState.parent')
4 réponses
En Utilisant Le Banc D'Essai
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [YourComponent],
imports: [],
providers: [
{
provide: ActivatedRoute, useValue: {
params: Observable.of({ id: 'test' })
}
}
]
})
.compileComponents();
}));
AcitvatedRoute est une interface selon angular2 docs, donc ce que j'ai fait est implémente un MockActivatedRoute
import {Observable} from 'rxjs';
import {Type} from '@angular/core';
import {ActivatedRoute,Route,ActivatedRouteSnapshot,UrlSegment,Params,Data } from '@angular/router';
export class MockActivatedRoute implements ActivatedRoute{
snapshot : ActivatedRouteSnapshot;
url : Observable<UrlSegment[]>;
params : Observable<Params>;
queryParams : Observable<Params>;
fragment : Observable<string>;
data : Observable<Data>;
outlet : string;
component : Type<any>|string;
routeConfig : Route;
root : ActivatedRoute;
parent : ActivatedRoute;
firstChild : ActivatedRoute;
children : ActivatedRoute[];
pathFromRoot : ActivatedRoute[];
toString() : string{
return "";
};
}
Et remplacez le ActivatedRoute
, dans mes tests, pour MockActivatedRoute
comme ceci
beforeEach(()=>{
route = new MockActivatedRoute();
route.parent = new MockActivatedRoute();
route.parent.params = Observable.of({id:"testId"});
questionnaireService = jasmine.createSpyObj('QuestionnaireService', ['getQuestionsForQuestionnaire']);
questionnaireService.getQuestionsForQuestionnaire.and.callFake(() => Observable.of(undefined));
component = new QuestionnaireQuestionsComponent(route, questionnaireService);
});
Pour toute personne nouvelle à cette question le angular.io les documents couvrent ce scénario. Voir ici
Selon la documentation ci-dessus:
Créer ActivatedRouteStub
classe à utiliser comme test double pour ActivatedRoute
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { convertToParamMap, ParamMap, Params } from '@angular/router';
/**
* An ActivateRoute test double with a `paramMap` observable.
* Use the `setParamMap()` method to add the next `paramMap` value.
*/
export class ActivatedRouteStub {
// Use a ReplaySubject to share previous values with subscribers
// and pump new values into the `paramMap` observable
private subject = new ReplaySubject<ParamMap>();
constructor(initialParams?: Params) {
this.setParamMap(initialParams);
}
/** The mock paramMap observable */
readonly paramMap = this.subject.asObservable();
/** Set the paramMap observables's next value */
setParamMap(params?: Params) {
this.subject.next(convertToParamMap(params));
};
}
Puis utilisez le talon dans la classe de test comme suit:
activatedRoute.setParamMap({ id: '1234' });
Vous pouvez aussi simple plass {params: {searchTerm: 'this is not me'}} as any) as ActivatedRouteSnapshot
Code détaillé
(service.resolve(({params: {id: 'this is id'}} as any) as ActivatedRouteSnapshot,
{} as RouterStateSnapshot)as Observable<xyzResolveData>)
.subscribe((data) => {
expect((data as xyzResolveData).results).toEqual(xyzData.results);
});