Angular网站上有很多测试都成功
设置此项无需等待 whenStablehttps://github.com/angular/angular/blob/874243279d5fd2bef567a13e0cef8d0cdf68eec1/modules/%40angular/forms/test/template_integration_spec.ts#L1043 https://github.com/angular/angular/blob/874243279d5fd2bef567a13e0cef8d0cdf68eec1/modules/%40angular/forms/test/template_integration_spec.ts#L1043
那是因为这些测试中的所有代码都在内部执行fakeAsync
当你开火时的区域fixture.detectChanges();
within beforeEach
. So fakeAsync
zone 不知道其范围之外的异步操作。当你打电话时detectChanges
第一次ngModel
已初始化
NgModel.prototype.ngOnChanges = function (changes) {
this._checkForErrors();
if (!this._registered)
this._setUpControl(); //<== here
并获取输入事件的正确回调
NgForm.prototype.addControl = function (dir) {
var _this = this;
resolvedPromise.then(function () { // notice async operation
var container = _this._findContainer(dir.path);
dir._control = (container.registerControl(dir.name, dir.control));
setUpControl(dir.control, dir); // <== here
inside setUpControl
你可以看到将被调用的函数input
event
dir.valueAccessor.registerOnChange(function (newValue) {
dir.viewToModelUpdate(newValue);
control.markAsDirty();
control.setValue(newValue, { emitModelToViewChange: false });
});
1)所以如果你搬家fixture.detectChanges
from beforeEach
根据您的测试,它应该可以工作:
it('submits the value', fakeAsync(() => {
spyOn(component, 'showWorkout').and.callThrough();
fixture.detectChanges();
skillCount = element.query(By.css('#skillCount')).nativeElement;
submitButton = element.query(By.css('#buildWorkout')).nativeElement;
tick();
skillCount.value = '10';
dispatchEvent(skillCount, 'input');
fixture.detectChanges();
submitButton.click();
fixture.detectChanges();
expect(component.showWorkout).toHaveBeenCalledWith('10');
}));
笨蛋的例子 https://plnkr.co/edit/NWqtnlcbR6FQwiZ1gpDQ?p=preview
但这个解决方案看起来非常复杂,因为您需要重写代码才能移动fixture.detectChanges
在你的每一个it
声明(并且还有一个问题skillCount
, submitButton
etc)
2)正如迪尼斯特罗所说async
和...一起whenStable
还应该帮助你:
it('submits the value', async(() => {
spyOn(component, 'showWorkout').and.callThrough();
fixture.whenStable().then(() => {
skillCount.value = '10';
dispatchEvent(skillCount, 'input');
fixture.detectChanges();
submitButton.click();
fixture.detectChanges();
expect(component.showWorkout).toHaveBeenCalledWith('10');
})
}));
笨蛋的例子 https://plnkr.co/edit/pWZpa1257921xuI1lmfn?p=preview
但是等等,为什么我们必须改变我们的代码呢?
3)只需添加async
到你的 beforeEach 函数
beforeEach(async(() => {
fixture = TestBed.createComponent(StartworkoutComponent);
component = fixture.componentInstance;
element = fixture.debugElement;
fixture.detectChanges();
}));
笨蛋的例子 https://plnkr.co/edit/bRR6qxrqj4cd8zP7iMi5?p=preview