Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular unit Testing : TypeError: Cannot read property 'root' of undefined

Tags:

I'm working on unit testing under my Angular app.

My version of Angular is 4.0.0.

My component look like this:

component.ts:

import { GdfaClientService } from '../../../service/gdfa-client.service'; import { SharedclientService } from '../../../service/sharedclient.service'; import { Client } from '../../model/client'; import { RouteNavigator } from '../../util/route-navigator'; import { Component, OnInit } from '@angular/core'; import {MonitoringService} from '../../../service/monitoring.service'; @Component({   selector: 'app-queue-again',   templateUrl: './queue-again.component.html',   styleUrls: ['./queue-again.component.css'], }) export class QueueAgainComponent implements OnInit {    //-- variables --//   showError = false;   queueChoices = [];   selectedQueue;   selectedReason;   requestInProgress = false;   client: Client;   errorMessage: string;   queues: any;   bankNotAllowed: boolean = false;    constructor(private sharedclientService: SharedclientService, private gdfaClientService: GdfaClientService     , private router: RouteNavigator, private monitoringService: MonitoringService) { }    ngOnInit() {     this.client = this.sharedclientService.getShared360Client();     this.getQueues();     this.bankNotAllowed = this.sharedclientService.bankNotAllowed;   }     goToPrevious() {     this.router.goToHomeAccordingToProfile();   }    queueAgain() {     let currentNd = "";     let currentUniverse = "";     let currentCuid = "";     if (!this.selectedReason) {       return;     }     this.requestInProgress = true;      let reg = {       registrationId: this.client.registration.gdfaId,       gdfaQueueId: this.selectedQueue.id,       gdfaReasonId: this.selectedReason.id,       firstProfile: (this.client.firstProfile ? true : false)     };      this.gdfaClientService.queueAgain(reg).then(any => {         currentCuid = this.client.clientIdentity.customerId;          if (this.client.fromAdvSearch == undefined || this.client.fromAdvSearch == false) {        currentNd = this.client.nd;       if (currentNd != undefined && currentNd != "") {         if (currentNd == "0000000000") {           currentNd = "";           currentUniverse = "";         }         if (currentNd.substring(0, 2) == "06" || currentNd.substring(0, 2) == "07") {           currentUniverse = "Mobile";         } else {           currentUniverse = "Fixe";         }       }         }       this.trackReinsertClient(currentCuid, currentNd, currentUniverse);       this.requestInProgress = false;       this.showError = false;       this.sharedclientService.setShared360Client(new Client());       this.goToPrevious();     })       .catch(error => {         this.requestInProgress = false;         this.showError = true;         switch (error.status) {           case 403:             this.errorMessage = "Erreur lors de la réinjection du client : utilisateur inconnu";             console.log(this.errorMessage);             break;           case 500:             this.errorMessage = "Réinscription impossible";             console.log(this.errorMessage);             break;           default:             this.errorMessage = "Erreur lors de la réinjection du client";             console.log(this.errorMessage);         }       });   };     trackReinsertClient(cuid, nd, universe) {     let uri = "/api/gdfa/client/registration/reinsert";     let httpMethod = "PUT";     let name = "réinjection d'un client dans la file d'attente";     console.log('trackReinsertClient <' + cuid + '>');     this.monitoringService.trackingAction(name, uri, httpMethod, null, cuid, nd, universe);    }    selectQueue(queue) {     this.selectedQueue = queue;     this.selectedReason = false;   };    isSelectedQueue(queue) {     return this.selectedQueue.shortName == queue.shortName;   }    getQueues() {     let queueList = this.client.registration.queueAgainChoices;     // Search for residentiel queue and put it as selectedQueue     let indexSAVSAUMobile = -1;     let indexSAVSAUInternet = -1;     for (let queue of queueList) {       if (queue.shortName == 'RES')         this.selectedQueue = queue;     }      this.queues = queueList;     return queueList;   }    selectReason(reason) {     this.selectedReason = reason;    }     isSelectedReason(reason) {     if (this.selectedReason) {       return this.selectedReason.id == reason.id;     }     return null   }    getReasons(queue) {     let reasonList = this.selectedQueue.reasons;     return reasonList;   } } 

component.html:

<div>     <div [hidden]="!requestInProgress" id="div-spinner">         <img src="/assets/images/indicateur-attente-grand.gif"             class="spinner-loader" />     </div>     <div class="row">         <!-- fermeture de la recherche avancée -->         <div class="col-xs-1 pull-right closeCross">             <img id="ngClick_goToPreviousFromQueueAgain"                 src="/assets/images/asset_icon_close_popup_gray.png"                 class="pull-right mousePointer" (click)="goToPrevious()" />         </div>     </div>     <div class="row">         <div class="col-xs-10 col-xs-offset-1 error-message"             *ngIf="showError">{{errorMessage}}</div>         <div             class="col-xs-10 col-xs-offset-1 col-sm-3 col-sm-offset-0 register-bloc">             <div class="titre_bloc">File d'attente</div>             <div id="files-bloc">                 <div id="ngClick_selectQueueAgain" class="file-cell "                     *ngFor="let queue of queues | orderBy : 'id'"                            [ngClass]="{ 'selected-shop-queue': isSelectedQueue(queue)}"                     (click)='selectQueue(queue)'>                     <div class="vertical-center horizontal-middle file_nom">                         <div>{{queue.name}}</div>                     </div>                 </div>             </div>         </div>         <div             class="col-xs-10 col-xs-offset-1 col-sm-6 col-sm-offset-0 register-bloc">             <div class="titre_bloc">Motifs</div>             <div id="motifs-bloc">                 <div id="ngClick_queueAgain" class="motif-cell"                     [ngClass]="{'motif-cell-pro': selectedQueue?.reasons?.length == 4, 'motif-cell-selected':isSelectedReason(reason),                     'hide-class': (bankNotAllowed && reason.id === 12)}" [hidden]="bankNotAllowed && reason.id === 12"                     *ngFor="let reason of selectedQueue?.reasons | orderBy : 'motifOrder'"                     (click)='selectReason(reason)'>                     <div *ngIf="!bankNotAllowed || reason.id !== 12" class="mIcon">                             <img                                 src="/bower_components/nomadis/images-no-cache/{{reason?.imageName}}"                                 [ngClass]="{'motif-unique': client?.registration?.queue?.reasons?.length == 1}" />                             <span>{{reason.name}}</span>                     </div>                 </div>             </div>             <div class="col-sm-offset-4 col-sm-4  btn-validate-reinsert">                 <input id="validateReinsertBtn" type="submit" value="Valider"                     [ngClass]="{'queueAgain-disabled': !selectedReason}"                     class="btn btn-lg btn-primary btn-block"                     (click)='queueAgain()' />             </div>         </div>     </div>  </div> <router-outlet></router-outlet> 

As you can see I'm not using routeLink.

Within my test file config I've done this:

component.spec.ts:

import {async, ComponentFixture, TestBed, tick, fakeAsync} from '@angular/core/testing'; import {QueueAgainComponent} from './queue-again.component'; import {OrderByPipe} from 'app/home/pipe/order-by.pipe'; import {SharedclientService} from 'app/service/sharedclient.service'; import {GdfaClientService} from 'app/service/gdfa-client.service'; import {AuthHttp, AuthConfig, AUTH_PROVIDERS, provideAuth} from 'angular2-jwt'; import {HttpModule} from '@angular/http'; import {EnvVarsService} from 'app/service/env-vars.service'; import {RouteNavigator} from 'app/home/util/route-navigator'; import {Router} from '@angular/router'; import {Observable} from 'rxjs/Observable'; import * as QueueAgainMocks from 'TU/mocks/queue-again-mocks'; import {RouterTestingModule} from '@angular/router/testing'; import { NO_ERRORS_SCHEMA } from '@angular/core';  describe('QueueAgainComponent', () => {     let comp: QueueAgainComponent;     let fixture: ComponentFixture<QueueAgainComponent>;     let sharedclientService: SharedclientService;     let gdfaClientService: GdfaClientService;     let getShared360Client: jasmine.Spy;     let queueAgain: jasmine.Spy;     let client = QueueAgainMocks.CUSTOMER_MOCK;     let selectedQueue = QueueAgainMocks.SELECTED_QUEUE_MOCK;     let selectedReason = QueueAgainMocks.SELECTED_REASON;     let mockRouter = {         navigate: jasmine.createSpy('navigate')     };      // TestBed preparation (async)     beforeEach(async(() => {         TestBed.configureTestingModule({             imports: [HttpModule , RouterTestingModule],             declarations: [QueueAgainComponent, OrderByPipe],             providers: [SharedclientService, GdfaClientService, AuthHttp, EnvVarsService, RouteNavigator,                 {provide: Router, useValue: mockRouter},                 provideAuth({                     headerName: 'Authorization',                     headerPrefix: 'bearer',                     tokenName: 'token',                     tokenGetter: (() => localStorage.getItem('id_token')),                     globalHeaders: [{'Content-Type': 'application/json'}],                     noJwtError: true                 })             ],             schemas: [ NO_ERRORS_SCHEMA ]         }).compileComponents();     }));      // Fixture & Spies declarations     beforeEach(() => {         // Creation of the component fixture         fixture = TestBed.createComponent(QueueAgainComponent);         comp = fixture.componentInstance;         fixture.detectChanges();  // this line will call components ngOnInit() method           // Getting Services instances from fixture         sharedclientService = fixture.debugElement.injector.get(SharedclientService);         gdfaClientService = fixture.debugElement.injector.get(GdfaClientService);          // Call of fake methods of `sharedclientService` from the AlertServiceSpy         getShared360Client = spyOn(sharedclientService, 'getShared360Client').and.returnValue(client);         // Call of fake methods of `gdfaClientService` from the AlertServiceSpy         queueAgain = spyOn(gdfaClientService, 'queueAgain').and.callFake((reg) => {             return Observable.of('ok');         });          comp.ngOnInit();     });     // Test case of component compilation     it('should be defined', () => {         expect(comp).toBeDefined();     }); }); 

Although I've imported NO_ERRORS_SCHEMA and I've used a mockRouter, it seems that something is still going wrong with routing with this error:

TypeError: Cannot read property 'root' of undefined        at rootRoute (node_modules/@angular/router/bundles/router.umd.js:6110:30)       at _callFactory (packages/core/src/view/ng_module.ts:185:1)       at _createProviderInstance$1 (packages/core/src/view/ng_module.ts:124:1)       at resolveNgModuleDep (node_modules/@angular/core/bundles/core.umd.js:9517:17)       at _createClass (packages/core/src/view/ng_module.ts:158:1)       at _createProviderInstance$1 (packages/core/src/view/ng_module.ts:121:1)       at resolveNgModuleDep (node_modules/@angular/core/bundles/core.umd.js:9517:17)       at NgModuleRef_.Object.<anonymous>.NgModuleRef_.get (node_modules/@angular/core/bundles/core.umd.js:10609:16)       at resolveDep (node_modules/@angular/core/bundles/core.umd.js:11112:45)       at createClass (node_modules/@angular/core/bundles/core.umd.js:10976:32)       at createDirectiveInstance (node_modules/@angular/core/bundles/core.umd.js:10796:37)       at createViewNodes (packages/core/src/view/view.ts:354:1)       at createRootView (node_modules/@angular/core/bundles/core.umd.js:12139:5)       at callWithDebugContext (packages/core/src/view/services.ts:815:1)       at Object.debugCreateRootView [as createRootView] (node_modules/@angular/core/bundles/core.umd.js:12842:12)       at ComponentFactory_.Object.<anonymous>.ComponentFactory_.create (node_modules/@angular/core/bundles/core.umd.js:9904:46)       at initComponent (node_modules/@angular/core/bundles/core-testing.umd.js:924:49)       at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:392:26)       at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:79:39)       at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:391:32)       at Object.onInvoke (node_modules/@angular/core/bundles/core.umd.js:3922:33)       at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:391:32)       at Zone.Object.<anonymous>.Zone.run (node_modules/zone.js/dist/zone-node.js:142:43)       at NgZone.Object.<anonymous>.NgZone.run (node_modules/@angular/core/bundles/core.umd.js:3853:69)       at TestBed.Object.<anonymous>.TestBed.createComponent (packages/core/testing/src/test_bed.ts:471:1)       at Function.Object.<anonymous>.TestBed.createComponent (node_modules/@angular/core/bundles/core-testing.umd.js:691:29)       at src/app/home/advisor/queue-again/queue-again.component.spec.ts:53:27 

From the last line of the log that points on the 53:27 line which is exactly:

fixture = TestBed.createComponent(QueueAgainComponent); 

So it seems that it's not able to create the fixture.

Any ideas?

like image 917
firasKoubaa Avatar asked Nov 06 '17 15:11

firasKoubaa


1 Answers

I had the same problem, just figured it out. Remove the line:

{provide: Router, useValue: mockRouter} 

and it will work.

The thing is when you import RouterTestingModule you should remove all router mocked providers, save for ActiveRoute, etc.

like image 175
teter Avatar answered Oct 08 '22 14:10

teter