2016-11-24 80 views
13

比方说,我有这个如何在angular2中模拟一个activatedRoute父路由用于测试目的?

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


} 

我的部件实际上相当不错的了。问题是我想单元测试它,但我无法弄清楚如何模拟this.route.parent对象。下面是我的测试失败

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

测试失败,出现此错误

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

尝试,只是使用'{父:{PARAMS:可观察.of({ID: “testId”}) }} as ActivatedRoute'而不是一个真正的ActivatedRoute –

+0

不会编译我需要一个ActivatedRoute对象 –

+0

你添加了'as ActivatedRoute'吗? –

回答

11

AcitvatedRoute根据angular2 docs的接口,所以我所做的是实现了一个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 ""; 
    }; 
} 

和只需在我的测试中替换ActivatedRoute就可以了MockActivatedRoute这样

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

谢谢你的这一点,即使你不关心父母的激活路线也是非常有用的。问题:您是否有理由更新组件而不注入路由和服务? – glitchbane

+0

仅仅因为我没有测试组件的行为......所以不需要真的注入它,组件不应该改变我的测试用例 –

+0

你也可以参考文档:https://angular.io/docs/ ts/latest/testing#!#create-an-_observable_-test-double – peinearydevelopment

18

利用测试床

​​

+0

中的工作是否会在编译时非常缓慢,并且在没有必要时不必加载TestBed。 –

+0

如果我想要怎么办赶上这个:this.returnUrl = this.route.snapshot.queryParams ['returnUrl'] || '/ someurl'; ? – TeodorKolev

0

你也可以简单赛普拉斯{params: {searchTerm: 'this is not me'}} as any) as ActivatedRouteSnapshot

detailds代码

(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); 
    }); 
相关问题