2016-08-12 101 views
7

我想測試使用其他服務的組件。我想通過提供服務模擬來分離組件。在RC5之前,我可以簡單地使用addproviders,它現在已被棄用,並將由下一個RC刪除。相反,我必須使用TestBed。當我提供模擬角度出於某種原因時,請繼續尋找模擬依賴的服務。並拋出一個DI exception。當我提供測試的所有依賴時,我不想重複每個測試套件。這打破了基本的面向對象原則。 我的測試套件:Angular 2 TestBed with mocks

describe('Component: DummyRestApi',() => { 

    class DummyRestApiTestService { 

    GetAll() { 

     return Rx.Observable.create(observer => { 

     let data:Data[] = []; 

     data.push({ 
      id: 0, 
      data: 'data' 
     }); 

     observer.next(data); 
     observer.complete(); 

     }); 
    } 

    Add(data) { 
    } 
    } 
    let fixture; 
    let myMockWindow:Window; 
    // ToDo use the mocks 
    beforeEach(() => { 
    myMockWindow = <any> {location: <any> {hostname: '127.0.0.1'}}; 
    TestBed.configureTestingModule({ 
     declarations: [DummyRestApiComponent], 
     providers: [ 
     // ServerAddressResolverService, 
     DummyRestApiComponent, 
     // ConfigurationService, 
     {provide: DummyRestApiService, useClass: DummyRestApiTestService}, 
     // {provide: Window, useValue: myMockWindow} 
     ], 
     imports: [FormsModule, HttpModule] 
    }); 
    TestBed.compileComponents().catch(error => console.error(error)); 


    // addProviders([ 
    // DummyRestApiComponent, 
    // {provide: DummyRestApiService, useClass: DummyRestApiTestService}, 
    // ]); 
    }); 


    describe('Initializing',() => { 

    beforeEach(async(() => { 
     console.log('Compiling'); 
     TestBed.compileComponents().catch(error => console.error(error)); 
     console.log('Compiling again'); 
    })); 

    it('should create an instance', async(() => { 
     var fixture = TestBed.createComponent(DummyRestApiComponent); 
     fixture.detectChanges(); 
     expect(fixture.debugElement.componentInstance).toBeTruthy(); 
     } 
    )); 

}); 

角2.0.0 RC5

+0

我證實了這一點。您必須爲該服務指定導入,就好像它沒有被模擬。至少在RC5中。不過,該測試將使用模擬服務。 – Dave

回答

2

我剛剛更新了我的種子項目RC5和我的測試套件,一個簡單的待辦事項組件看起來是這樣的:

import { provide } from '@angular/core'; 
import { TestBed, ComponentFixture, async } from '@angular/core/testing'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/observable/of'; 

import { TodoModule } from './todo.module'; 
import { TodoComponent } from './todo.component'; 
import { Todo, TodoService } from './todo.service'; 

class MockTodoService { 
    get todos$(): Observable<Todo[]> { 
     return Observable.of<Todo[]>([ 
      { task: 'Task 1', description: 'Description 1', completed: false }, 
      { task: 'Task 2', description: 'Description 2', completed: false } 
     ]); 
    } 

    loadAll() { } 

    add(newTodo: Todo) { } 
} 

describe('TodoComponent',() => { 

    beforeEach(() => { 
     this.service = new MockTodoService(); 

     TestBed.configureTestingModule({ 
      imports: [TodoModule], 
      providers: [provide(TodoService, { useValue: this.service })] 
     }); 

     this.fixture = TestBed.createComponent(TodoComponent); 
    }); 

    it('should print out todo tasks', async(() => { 
     this.fixture.whenStable().then(() => { 
      let element = this.fixture.nativeElement; 
      this.fixture.detectChanges(); 

      expect(element.querySelectorAll('li').length).toBe(2); 
     }); 
    })); 

    it('should call the service on init', async(() => { 
     this.fixture.whenStable().then(() => { 
      spyOn(this.service, 'loadAll'); 
      this.fixture.detectChanges(); 

      expect(this.service.loadAll).toHaveBeenCalled(); 
     }); 
    })); 
}); 

種子項目本身可以在https://github.com/froko/ng2-seed-webpack

希望這會有所幫助。

+2

但[RC5更改日誌](https://github.com/angular/angular/blob/master/CHANGELOG.md#breaking-changes-1)也聲明「現在ngModel在更新時總是異步的,這意味着在測試中,不是調用'ComponentFixture.detectChanges',而是需要使用'ComponentFixture.whenStable',它是異步的。「你已經在使用'whenStable',但你還在使用'detectChanges'。如果你現在只是刪除'this.fixture.detectChanges()',你的測試是否仍然有效? –

5

請注意,帕特里克Ineichens答案使用提供,這已被棄用。

providers: [provide(TodoService, { useValue: this.service })] 

應改爲閱讀:

providers: [{provide:TodoService, useValue: this.service }]