2016-11-24 1 views
13

Sagen wir, ich dieseWie wird eine aktivierteRoute-Eltern-Route in angular2 zu Testzwecken gespottet?

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


} 

Meine Komponente haben ziemlich gut tatsächlich funktioniert. Problem ist, dass ich Einheit es testen will, aber ich kann nicht herausfinden, wie man das this.route.parent Objekt verspottet. Hier ist mein Test, der

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

den Test nicht besteht mit diesem Fehler

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

Versuchen und nur 'verwenden {parent: {params: beobachtbare .of ({id: "testId"}) }} als ActivatedRoute' anstelle einer echten ActivatedRoute –

+0

Kompilieren nicht nötig Ich brauche ein ActivatedRoute-Objekt –

+0

Hast du die 'as ActivatedRoute' hinzugefügt? –

Antwort

11

AcitvatedRoute versagt ist eine Schnittstelle zu angular2 docs nach, also was ich habe ist ein 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 ""; 
    }; 
} 

implementiert und Ersetzen Sie einfach die ActivatedRoute in meinen Tests für MockActivatedRoute wie diese

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

Vielen Dank dafür, es ist sehr hilfreich, auch für aktivierte Routen, wo Sie nicht über die Eltern betroffen sind. Frage: Gibt es einen Grund, warum Sie lieber die Komponente neu erstellen, anstatt die Route und den Service zu injizieren? – glitchbane

+0

Nur weil ich das Verhalten der Komponente nicht teste ... also keine Notwendigkeit, es wirklich zu injizieren, sollte die Komponente nichts in meinen Testfällen ändern –

+0

Sie können auch auf die Dokumentation verweisen: https://angular.io/docs/ ts/next/testing #! # create-an-_observable_-test-double – peinearydevelopment

18

Mit TestBed

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

+0

TestBed ist manchmal sehr langsam, wenn Sie kompilieren, und Sie müssen TestBed nicht laden, wenn es nicht notwendig ist. –

+0

Was, wenn ich möchte Fange das: this.returnUrl = this.route.snapshot.queryParams ['returnUrl'] || '/ someurl'; ? – TeodorKolev

0

Sie können auch einfach 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<xyzResolveData>) 
    .subscribe((data) => { 
     expect((data as xyzResolveData).results).toEqual(xyzData.results); 
    }); 
Verwandte Themen