2017-02-22 52 views
0

我有一個關於在an​​gular2中測試路由組件的問題。測試組件,這取決於路由參數

這是一個簡單的組件,它取決於具有參數'foo'的路線。組件中的屬性foo將被設置爲參數的值。

import {Component, OnInit} from '@angular/core'; 
import {ActivatedRoute, Params} from '@angular/router'; 

@Component({ 
    selector: 'my-component', 
    templateUrl: './my-component.html' 
}) 
export class MyComponent implements OnInit 
{ 
    foo: string; 

    constructor(
     private route: ActivatedRoute 
    ) 
    { 
    } 

    ngOnInit() 
    { 
     this.route.params.subscribe((params: Params) => { 
      this.foo = params['foo']; 
     }); 
    } 
} 

現在我想測試一下,如果將使用路由創建組件,則param將被正確設置。所以我想要有一個地方expect(component.foo).toBe('3');

import {TestBed, ComponentFixture, async} from '@angular/core/testing'; 
import {DebugElement} from '@angular/core'; 
import {By} from '@angular/platform-browser'; 
import {Params, ActivatedRoute} from '@angular/router'; 

import {Observable} from 'rxjs'; 

import {MyComponent} from './MyComponent'; 

describe('MyComponent',() => { 
    let mockParams, mockActivatedRoute; 

    let component: MyComponent; 
    let fixture: ComponentFixture<MyComponent>; 
    let debugElement: DebugElement; 
    let element: HTMLElement; 

    beforeEach(async(() => { 
     mockParams = Observable.of<Params>({foo: '3'}); 
     mockActivatedRoute = {params: mockParams}; 

     TestBed.configureTestingModule({ 
      declarations: [ 
       MyComponent 
      ], 
      providers: [ 
       {provide: ActivatedRoute, useValue: mockActivatedRoute} 
      ] 
     }).compileComponents(); 
    })); 

    beforeEach(() => { 
     fixture = TestBed.createComponent(MyComponent); 
     component = fixture.componentInstance; 

     debugElement = fixture.debugElement; 
     element = debugElement.nativeElement; 

     fixture.detectChanges(); 
    }); 

    it('should set foo to "3"',() => { 
     expect(component.foo).toBe('3'); 
    }); 
}); 

我的問題是,我不知道如何等待,直到路線的解析結束,我可以做一個expect()。在這個例子中,測試失敗,它說「預計未定義爲'3'」。

有人可以幫我嗎?!

謝謝!

回答

1

好的,在angular2測試文檔中稍微閱讀一下,我看到了他們的ActivatedRouteStub類。我創建了這個存根類,並用這個新類替換了我原來的模擬。現在它正在工作(在每秒之前識別第mockActivatedRoute.testParams = {foo: '3'};行)。

import {TestBed, ComponentFixture, async} from '@angular/core/testing'; 
import {DebugElement} from '@angular/core'; 
import {By} from '@angular/platform-browser'; 
import {Params, ActivatedRoute} from '@angular/router'; 

import {Observable} from 'rxjs'; 

import {MyComponent} from './MyComponent'; 

import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 

@Injectable() 
export class ActivatedRouteStub 
{ 
    private subject = new BehaviorSubject(this.testParams); 
    params = this.subject.asObservable(); 

    private _testParams: {}; 
    get testParams() { return this._testParams; } 
    set testParams(params: {}) { 
     this._testParams = params; 
     this.subject.next(params); 
    } 
} 

describe('MyComponent',() => { 
    let mockParams, mockActivatedRoute; 

    let component: MyComponent; 
    let fixture: ComponentFixture<MyComponent>; 
    let debugElement: DebugElement; 
    let element: HTMLElement; 

    beforeEach(async(() => { 
     mockActivatedRoute = new ActivatedRouteStub(); 

     TestBed.configureTestingModule({ 
      declarations: [ 
       MyComponent 
      ], 
      providers: [ 
       {provide: ActivatedRoute, useValue: mockActivatedRoute} 
      ] 
     }).compileComponents(); 
    })); 

    beforeEach(() => { 
     fixture = TestBed.createComponent(MyComponent); 
     component = fixture.componentInstance; 

     debugElement = fixture.debugElement; 
     element = debugElement.nativeElement; 

     mockActivatedRoute.testParams = {foo: '3'}; 

     fixture.detectChanges(); 
    }); 

    it('should set foo to "3"',() => { 
     expect(component.foo).toBe('3'); 
    }); 
}); 

您認爲這是正確的方法嗎?

+0

你的測試,驗證組件數據根據路由參數設置,看起來不錯。測試僅依賴於ActivatedRoute的模擬實現,而不是真正的實現。那很好。單元測試應儘可能隔離。像這樣的測試的目的是僅在一個組件本身中識別問題,而不是與其他組件或服務或Angular類或瀏覽器的交互。如果您引入了其他此類不必要的交互,則會覆蓋測試結果,因爲其他內容可能會掩蓋組件中的問題。 – Will