visual unit tests test studio run how generate code basics unit-testing angular typescript mocking jasmine

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(); }));