我正在尝试对我的组件的ngOnInit()函数中的异步服务设置的数组进行单元测试。
export class DashboardComponent implements OnInit {
todos: Todo[] = [];
constructor(public todoService: TodoService) {}
ngOnInit(): void {
this.todoService.getTodos()
.then(todos => this.todos = todos.slice(1, 5));
}
}
当我尝试用这样的函数测试它时:
it('should load four todos for dashboard', function(done) {
expect(component.todos.length).toEqual(4);
});
我收到0不等于4的错误,因为承诺尚未解决。我能让它工作的唯一方法是将服务公开并运行“脏”代码:
it('should load four todos for dashboard', function(done) {
var todos = component.todoService.getTodos();
todos.then(x => {
expect(x.length).toEqual(6);
expect(component.todos.length).toEqual(4)
});
done();
});
但确实有更好更清洁的方法,所以欢迎任何改进建议!
编辑1:在提示指向正确方向的dbandstra之后,我想出了这段代码:
describe('DashboardComponent', () => {
beforeEach( async(() => {
TestBed.configureTestingModule({
declarations: [
DashboardComponent, EmptyComponent,
RouterLinkStubDirective, RouterOutletStubComponent
],
providers: [{provide: TodoService, useClass: FakeTodoService}]
})
.overrideComponent(TodoSearchComponent, EmptyComponent)
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(DashboardComponent);
comp = fixture.componentInstance;
});
}));
beforeEach(() => {
// TodoService actually injected into the component
let todoService = fixture.debugElement.injector.get(TodoService);
let spy = spyOn(todoService, 'getTodos')
.and.returnValue(Promise.resolve(todos));
// trigger initial data binding
fixture.detectChanges();
});
it('should load four todos for dashboard', () => {
fixture.whenStable().then(() => { // wait for async getTodos
fixture.detectChanges(); // update view with todos
expect(comp.todos.length).toEqual(4);
});
})
});
这就像一个魅力,谢谢!
编辑2:我还让它使用https://stackoverflow.com/a/39445420/3368833中建议的解决方案,使假服务同步如下:
class TodoServiceMock{
private data: Todo[];
getTodos() {
let todos = [ ...insert fake data here... ];
this.data = todos;
return this;
}
then(callback) {
callback(this.data);
}
}