55 votes

Comment simuler une route parent enabledRoute dans angular2 à des fins de test?

Disons que j'ai ça

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


}
 

Mon composant fonctionne plutôt bien. Le problème est que je veux le tester unitaire mais je ne peux pas comprendre comment se moquer de l'objet this.route.parent . Voici mon test qui échoue

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

Le test échoue avec cette erreur

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

58voto

Kevin Black Points 606

Utilisation de TestBed

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

30voto

S.Galarneau Points 1171

AcitvatedRoute est une interface selon les documents angular2, donc ce que j'ai fait implémente 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 "";
    };
}
 

et il suffit de remplacer le ActivatedRoute dans mes tests pour MockActivatedRoute comme ceci

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

19voto

ggolding Points 56

Pour tous ceux qui ne connaissent pas cette question, les documents angular.io couvrent ce scénario. Voir ici

Selon la documentation ci-dessus:

Créez la classe ActivatedRouteStub à utiliser comme test double pour 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));
  };
}
 

Et puis utilisez le stub dans la classe de test comme suit:

 activatedRoute.setParamMap({ id: '1234' });
 

3voto

Aniruddha Das Points 34

Vous pouvez également utiliser un plass simple {params: {searchTerm: 'this is not me'}} as any) as ActivatedRouteSnapshot

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X