2016-11-24 1 views
13

Скажем, у меня есть этотКак издеваться над активированным родительским маршрутизатором Маршрут в угловом2 для целей тестирования?

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

Try и просто использовать '{Родитель: {Титулы: Наблюдаемые .of ({ID: "TestID"}) }} как 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

Использование TestBed

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

+0

TestBed очень медленно, когда вы компилируете, и вам не нужно загружать TestBed, когда это не нужно. –

+0

Что делать, если я хочу catch this: 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); 
    });