Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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')  
like image 806
S.Galarneau Avatar asked Nov 24 '16 15:11

S.Galarneau


People also ask

How do you activate a mock route?

You can get it with TestBed. get(ActivatedRoute) in your it functions if you want to stock it in a variable. This way you can subscribe to your paramMap and retrieve multiple values - in this case testId and anotherId .

What does the ActivatedRoute interface allows you to access?

ActivatedRoutelink. Provides access to information about a route associated with a component that is loaded in an outlet. Use to traverse the RouterState tree and extract information from nodes.

How do I use ActivatedRoute?

Step 1: Import ActivatedRoute from Router module. import { ActivatedRoute } from '@angular/router'; Step 2: Inject ActivatedRoute in constructor. Now we have id in edit_quiz.

What is router and ActivatedRoute?

RouterState and ActivatedRoute are similar to their snapshot counterparts except that they expose all the values as observables, which are great for dealing with values changing over time. Any component instantiated by the router can inject its ActivatedRoute.


2 Answers

Using TestBed

 beforeEach(async(() => {      TestBed.configureTestingModule({        declarations: [YourComponent],        imports: [],        providers: [          {            provide: ActivatedRoute, useValue: {              params: Observable.of({ id: 'test' })            }          }        ]      })        .compileComponents();    }));
like image 158
Kevin Black Avatar answered Sep 21 '22 11:09

Kevin Black


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

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); }); 
like image 36
S.Galarneau Avatar answered Sep 20 '22 11:09

S.Galarneau