2

Я пишу блок-тест для моего компонента NavBar в угловом 2. У меня есть маршрутизатор, издевательский, и он передает все мои тесты; Однако, я создал службу для установки активного класса для маршрута, и это является причиной моего модульного тестирования на неудачу с ошибкой:Angular 2 Jasmine failing undefined не является объектом

undefined is not an object (evaluating 'this.router.url.substring')

NavActive службы

import { Injectable } from '@angular/core'; 
import { Router, RouterModule } from '@angular/router'; 

@Injectable() 
export class NavActiveService { 
    constructor(private router: Router) { 

    } 

    homeActive() { 
     if (this.router.url === '/') { 
      return '#0fecdb'; 
     } 
     else { 
      return '#00f'; 
     } 
    } 

    loginActive() { 
     if (this.router.url.substring(0,6) === '/login') { 
      return '#0fecdb'; 
     } 
     else { 
      return '#00f'; 
     } 
    } 

    uploadActive() { 
     if (this.router.url.substring(0,7) === '/upload') { 
      return '#0fecdb'; 
     } 
     else { 
      return '#00f'; 
     } 
    } 

    aboutActive() { 
     if (this.router.url.substring(0,5) === '/about') { 
      return '#0fecdb'; 
     } 
     else { 
      return '#00f'; 
     } 
    } 

    contactActive() { 
     if (this.router.url.substring(0,7) === '/contact') { 
      return '#0fecdb'; 
     } 
     else { 
      return '#00f'; 
     } 
    } 

    four04Active() { 
     if (this.router.url === '/**') { 
      return '#0fecdb'; 
     } 
     else { 
      return '#00f'; 
     } 
    } 
} 

Navbar Компонент

import { Component } from '@angular/core'; 
import { Router } from '@angular/router'; 
import { NavActiveService } from '../../../services/navactive.service'; 
import { GlobalEventsManager } from '../../../services/GlobalEventsManager'; 

@Component({ 
    moduleId: module.id, 
    selector: 'my-navbar', 
    templateUrl: 'navbar.component.html', 
    styleUrls:['navbar.component.css'], 
    providers: [NavActiveService] 
}) 
export class NavComponent { 
    showNavBar: boolean = true; 

    constructor(private router: Router, 
       private navactiveservice:NavActiveService, 
       private globalEventsManager: GlobalEventsManager){ 

    this.globalEventsManager.showNavBar.subscribe((mode:boolean)=>{ 
     this.showNavBar = mode; 
    }); 

    } 

} 

Navbar HTML

<div *ngIf="showNavBar"> 
<nav class="navbar navbar-fixed-top navbar-light bg-faded"> 
    <button class="navbar-toggler hidden-sm-up" type="button" data-toggle="collapse" data-target="#navbar"> 
    &#9776; 
    </button> 
    <div class="collapse navbar-toggleable-xs" id="navbar"> 
    <div class="container"> 
    <a class="navbar-brand" [routerLink]="'/'">My App</a> 
    <ul class="nav navbar-nav navbar-right"> 
     <li class="nav-item" > 
     <a class="nav-link" [routerLink]="'/'" [style.backgroundColor]="this.navactiveservice.homeActive()" > <i class="fa fa-home"></i> Home <span class="sr-only">(current)</span></a> 
     </li> 
     <li class="nav-item" > 
     <a class="nav-link" [routerLink]="'/upload'" [style.backgroundColor]="this.navactiveservice.uploadActive()" > <i class="fa fa-upload"></i> Upload </a> 
     </li> 
     <li class="nav-item" > 
     <a class="nav-link" [routerLink]="'/about'" [style.backgroundColor]="this.navactiveservice.aboutActive()" > <i class="fa fa-bar-chart"> </i> Tracking Data</a> 
     </li> 
     <li class="nav-item" > 
     <a class="nav-link" [routerLink]="'/login'" [style.backgroundColor]="this.navactiveservice.loginActive()" > <i class="fa fa-user"></i> Logout</a> 
     </li> 
    </ul> 
    </div> 
    </div> 
</nav> 
</div> 

Navbar Unit Test

import { ComponentFixture, TestBed, async } from '@angular/core/testing'; 
import { NavComponent } from './navbar.component'; 
import { DebugElement } from '@angular/core'; 
import { By }    from '@angular/platform-browser'; 
import { RouterLinkStubDirective, RouterOutletStubComponent } from '../../../../test/router-stubs'; 
import { Router } from '@angular/router'; 
import { GlobalEventsManager } from '../../../services/GlobalEventsManager'; 
import { NavActiveService } from '../../../services/navactive.service'; 
import { RouterModule } from '@angular/router'; 
import { SharedModule } from '../shared.module'; 


export function main() { 
    let comp: NavComponent; 
    let fixture: ComponentFixture<NavComponent>; 
    let mockRouter:any; 
    class MockRouter { 
     //noinspection TypeScriptUnresolvedFunction 
     navigate = jasmine.createSpy('navigate'); 
    } 

    describe('Navbar Componenet',() => { 

     beforeEach(async(() => { 
      mockRouter = new MockRouter(); 
      TestBed.configureTestingModule({ 
       imports: [ SharedModule ] 
      }) 

      // Get rid of app's Router configuration otherwise many failures. 
      // Doing so removes Router declarations; add the Router stubs 
       .overrideModule(SharedModule, { 
        remove: { 
         imports: [ RouterModule ], 

        }, 
        add: { 
         declarations: [ RouterLinkStubDirective, RouterOutletStubComponent ], 
         providers: [ { provide: Router, useValue: mockRouter }, GlobalEventsManager, NavActiveService ], 
        } 
       }) 

       .compileComponents() 

       .then(() => { 
        fixture = TestBed.createComponent(NavComponent); 
        comp = fixture.componentInstance; 
       }); 
     })); 

     tests(); 
    }); 


     function tests() { 
      let links: RouterLinkStubDirective[]; 
      let linkDes: DebugElement[]; 

      beforeEach(() => { 
       // trigger initial data binding 
       fixture.detectChanges(); 

       // find DebugElements with an attached RouterLinkStubDirective 
       linkDes = fixture.debugElement 
        .queryAll(By.directive(RouterLinkStubDirective)); 

       // get the attached link directive instances using the DebugElement injectors 
       links = linkDes 
        .map(de => de.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective); 
      }); 

      it('can instantiate it',() => { 
       expect(comp).not.toBeNull(); 
      }); 

      it('can get RouterLinks from template',() => { 
       expect(links.length).toBe(5, 'should have 5 links'); 
       expect(links[0].linkParams).toBe('/', '1st link should go to Home'); 
       expect(links[1].linkParams).toBe('/', '2nd link should go to Home'); 
      }); 

      it('can click upload link in template',() => { 
       const uploadLinkDe = linkDes[2]; 
       const uploadLink = links[2]; 

       expect(uploadLink.navigatedTo).toBeNull('link should not have navigated yet'); 

       uploadLinkDe.triggerEventHandler('click', null); 
       fixture.detectChanges(); 

       expect(uploadLink.navigatedTo).toBe('/upload'); 
      }); 
     } 
} 

Как я мог дразнить navActiveService так что мои тесты пройдены успешно?

ответ

1

В вашем NavActiveService, вы используете this.router.url.substring(0,7), но ваш Router заглушки не имеет url свойство. Он имеет только одну функцию navigate.

Возможно, для каждого теста вы можете просто установить значение для url.

mockRouter.url = '/contact' 

Или, если это не нужно менять для испытаний, просто добавьте его, когда вы его объявите.

class MockRouter { 
    url = '/'; 
    navigate = jasmine.createSpy('navigate'); 
} 
+0

Это была проблема, спасибо! – Bhetzie

Смежные вопросы