別のサービスを使用するコンポーネントをテストしようとしています。そして、サービスのモックを提供することでコンポーネントを分離したいと思います。 RC5より前は、addproviders
を使用できますが、これは現在非推奨であり、次のRCで削除されます。代わりに、TestBed
を使用する必要があります。モックを提供するときangular何らかの理由で、モックが依存するサービスを探し続けます。そしてDI exception
をスローします。すべての依存関係を提供すると、テストは機能しますが、テストスイートごとに繰り返したくない。これは基本的なOO原則を破る。私のテストスイート:
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();
}
));
});
Angular 2.0.0-RC5
Patrick Ineichensの回答はprovideを使用していることに注意してください。これは、非推奨です。
providers: [provide(TodoService, { useValue: this.service })]
代わりに読む必要があります:
providers: [{provide:TodoService, useValue: this.service }]
シードプロジェクトをRC5に更新したところ、単純なtodoコンポーネントのテストスイートは次のようになりました。
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 にあります。
お役に立てれば。