How to mock an activatedRoute parent Route in angular2 for testing purposes?

匿名 (未验证) 提交于 2019-12-03 01:26:01

问题:

Let's say I have this

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

My component is actually working pretty well. Problem is that I want to unit test it but I can't figure out how to mock the this.route.parent object. Here's my test that fails

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

The test fails with this error

TypeError: undefined is not an object (evaluating 'this._routerState.parent')  

回答1:

Using TestBed

 beforeEach(async(() => {     TestBed.configureTestingModule({       declarations: [YourComponent],       imports: [],       providers: [         {           provide: ActivatedRoute, useValue: {             params: Observable.of({ id: 'test' })           }         }       ]     })       .compileComponents();   }));


回答2:

AcitvatedRoute is an interface according to angular2 docs, so what I did is implements a 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;     params : Observable;     queryParams : Observable;     fragment : Observable;     data : Observable;     outlet : string;     component : Type|string;     routeConfig : Route;     root : ActivatedRoute;     parent : ActivatedRoute;     firstChild : ActivatedRoute;     children : ActivatedRoute[];     pathFromRoot : ActivatedRoute[];     toString() : string{         return "";     }; } 

and just replace the ActivatedRoute in my tests for MockActivatedRoute like this

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


回答3:

You can also simple plass {params: {searchTerm: 'this is not me'}} as any) as ActivatedRouteSnapshot

detailds code

  (service.resolve(({params: {id: 'this is id'}} as any) as ActivatedRouteSnapshot,     {} as RouterStateSnapshot)as Observable)     .subscribe((data) => {       expect((data as xyzResolveData).results).toEqual(xyzData.results);     }); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!