unit testing - unit - ¿Cómo simular una ruta principal activada en ruta2 para propósitos de prueba?
visual studio generate unit tests (4)
AcitvatedRoute es una interfaz de acuerdo con los docs angular2, así que lo que hice es implementar 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 "";
};
}
y simplemente reemplace el ActivatedRoute
en mis pruebas para MockActivatedRoute
como este
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);
});
Digamos que tengo esto
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;
});
});
}
}
Mi componente está funcionando bastante bien. El problema es que quiero probarlo por unidad, pero no puedo imaginar cómo burlarme del objeto this.route.parent
. Aquí está mi prueba que falla
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();
});
});
La prueba falla con este error
TypeError: undefined is not an object (evaluating ''this._routerState.parent'')
Para cualquier persona nueva en esta pregunta, los documentos de angular.io cubren este escenario. Ver here
Según la documentación anterior:
Cree la clase ActivatedRouteStub
para usarla como prueba doble para 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));
};
}
Y luego use el talón en la clase de prueba de la siguiente manera:
activatedRoute.setParamMap({ id: ''1234'' });
También puede hacer plass simple {params: {searchTerm: ''this is not me''}} as any) as ActivatedRouteSnapshot
código de detalle
(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);
});
Usando TestBed
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [YourComponent],
imports: [],
providers: [
{
provide: ActivatedRoute, useValue: {
params: Observable.of({ id: ''test'' })
}
}
]
})
.compileComponents();
}));