title: Angular unit Testing : TypeError: Cannot read property 'root' of undefined
body: <p>I'm working on unit testing under my Angular app.</p>
  
  <p>My version of Angular is 4.0.0.</p>
  
  <p>My component look like this:</p>
  
  <p><code>component.ts</code>: </p>
  
  <pre><code>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 =&gt; {
          currentCuid = this.client.clientIdentity.customerId;
  
          if (this.client.fromAdvSearch == undefined || this.client.fromAdvSearch == false) {
  
        currentNd = this.client.nd;
        if (currentNd != undefined &amp;&amp; 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 =&gt; {
          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 &lt;' + cuid + '&gt;');
      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;
    }
  }
  </code></pre>
  
  <p><code>component.html</code>:</p>
  
  <pre><code>&lt;div&gt;
      &lt;div [hidden]="!requestInProgress" id="div-spinner"&gt;
          &lt;img src="/assets/images/indicateur-attente-grand.gif"
              class="spinner-loader" /&gt;
      &lt;/div&gt;
      &lt;div class="row"&gt;
          &lt;!-- fermeture de la recherche avancée --&gt;
          &lt;div class="col-xs-1 pull-right closeCross"&gt;
              &lt;img id="ngClick_goToPreviousFromQueueAgain"
                  src="/assets/images/asset_icon_close_popup_gray.png"
                  class="pull-right mousePointer" (click)="goToPrevious()" /&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="row"&gt;
          &lt;div class="col-xs-10 col-xs-offset-1 error-message"
              *ngIf="showError"&gt;{{errorMessage}}&lt;/div&gt;
          &lt;div
              class="col-xs-10 col-xs-offset-1 col-sm-3 col-sm-offset-0 register-bloc"&gt;
              &lt;div class="titre_bloc"&gt;File d'attente&lt;/div&gt;
              &lt;div id="files-bloc"&gt;
                  &lt;div id="ngClick_selectQueueAgain" class="file-cell "
                      *ngFor="let queue of queues | orderBy : 'id'"       
                      [ngClass]="{ 'selected-shop-queue': isSelectedQueue(queue)}"
                      (click)='selectQueue(queue)'&gt;
                      &lt;div class="vertical-center horizontal-middle file_nom"&gt;
                          &lt;div&gt;{{queue.name}}&lt;/div&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div
              class="col-xs-10 col-xs-offset-1 col-sm-6 col-sm-offset-0 register-bloc"&gt;
              &lt;div class="titre_bloc"&gt;Motifs&lt;/div&gt;
              &lt;div id="motifs-bloc"&gt;
                  &lt;div id="ngClick_queueAgain" class="motif-cell"
                      [ngClass]="{'motif-cell-pro': selectedQueue?.reasons?.length == 4, 'motif-cell-selected':isSelectedReason(reason),
                      'hide-class': (bankNotAllowed &amp;&amp; reason.id === 12)}" [hidden]="bankNotAllowed &amp;&amp; reason.id === 12"
                      *ngFor="let reason of selectedQueue?.reasons | orderBy : 'motifOrder'"
                      (click)='selectReason(reason)'&gt;
                      &lt;div *ngIf="!bankNotAllowed || reason.id !== 12" class="mIcon"&gt;
                              &lt;img
                                  src="/bower_components/nomadis/images-no-cache/{{reason?.imageName}}"
                                  [ngClass]="{'motif-unique': client?.registration?.queue?.reasons?.length == 1}" /&gt;
                              &lt;span&gt;{{reason.name}}&lt;/span&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="col-sm-offset-4 col-sm-4  btn-validate-reinsert"&gt;
                  &lt;input id="validateReinsertBtn" type="submit" value="Valider"
                      [ngClass]="{'queueAgain-disabled': !selectedReason}"
                      class="btn btn-lg btn-primary btn-block"
                      (click)='queueAgain()' /&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  
  &lt;/div&gt;
  &lt;router-outlet&gt;&lt;/router-outlet&gt;
  </code></pre>
  
  <p>As you can see I'm not using <code>routeLink</code>.</p>
  
  <p>Within my test file config I've done this: </p>
  
  <p><code>component.spec.ts</code>:</p>
  
  <pre><code>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', () =&gt; {
      let comp: QueueAgainComponent;
      let fixture: ComponentFixture&lt;QueueAgainComponent&gt;;
      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(() =&gt; {
          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: (() =&gt; localStorage.getItem('id_token')),
                      globalHeaders: [{'Content-Type': 'application/json'}],
                      noJwtError: true
                  })
              ],
              schemas: [ NO_ERRORS_SCHEMA ]
          }).compileComponents();
      }));
  
      // Fixture &amp; Spies declarations
      beforeEach(() =&gt; {
          // 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) =&gt; {
              return Observable.of('ok');
          });
  
          comp.ngOnInit();
      });
      // Test case of component compilation
      it('should be defined', () =&gt; {
          expect(comp).toBeDefined();
      });
  });
  </code></pre>
  
  <p>Although I've imported <code>NO_ERRORS_SCHEMA</code> and I've used a <code>mockRouter</code>, it seems that something is still going wrong with routing with this error:</p>
  
  <pre><code>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.&lt;anonymous&gt;.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.&lt;anonymous&gt;.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.&lt;anonymous&gt;.ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:392:26)
        at ProxyZoneSpec.Object.&lt;anonymous&gt;.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:79:39)
        at ZoneDelegate.Object.&lt;anonymous&gt;.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.&lt;anonymous&gt;.ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:391:32)
        at Zone.Object.&lt;anonymous&gt;.Zone.run (node_modules/zone.js/dist/zone-node.js:142:43)
        at NgZone.Object.&lt;anonymous&gt;.NgZone.run (node_modules/@angular/core/bundles/core.umd.js:3853:69)
        at TestBed.Object.&lt;anonymous&gt;.TestBed.createComponent (packages/core/testing/src/test_bed.ts:471:1)
        at Function.Object.&lt;anonymous&gt;.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
  </code></pre>
  
  <p>From the last line of the log that points on the 53:27 line which is exactly:</p>
  
  <pre><code>fixture = TestBed.createComponent(QueueAgainComponent);
  </code></pre>
  
  <p>So it seems that it's not able to create the <em>fixture</em>.</p>
  
  <p>Any ideas?</p>