jasmine - 测试用例单独运行时通过,但在组中运行时失败
问题描述
我有以下几个测试用例,它们在单独执行时运行成功,但在组运行时随机失败。他们都使用setTimeout
. 它们位于单个文件中,以不同的方法spec
隔离。describe
例如。这个测试用例(使用setTimeout
)在我自己运行时通过,但是当我在组中运行时,它失败了。我怀疑这个问题与setTimeout
. 我尝试使用done
,但这并不能解决问题。
describe('AppComponent Test suite', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent,
...
],
imports: [
....
],
providers: [{provide: APP_BASE_HREF, useValue: '/'},
....]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
let componentDE = fixture.debugElement;
let componentNE:HTMLElement = componentDE.nativeElement;
componentNE.setAttribute("signup","someIncorrectValue");
fixture.detectChanges();
});
it('should show dialog message if the application has unrecognised value of signup attribute in url',(done)=>{
spyOn(component,'showDialog');
setTimeout(()=>{
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
},1000); done();
});
});
想象在同一个文件中有更多类似的测试用例,每个测试用例describe
都使用setTimeout
.
他们为什么会失败?如果问题是同步,我如何同步它们?
更新
我也试过了async
,await
但没有快乐!
it('should show dialog message if the application has unrecognised value of signup attribute in url',async ()=>{
spyOn(component,'showDialog');
await setTimeout(()=>{
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
},1000);
});
我还将调用移到了done
insidesetTimeout
的回调,但那里也没有任何乐趣。
it('should show dialog message if the application has unrecognised value of signup attribute in url', (done)=>{
spyOn(component,'showDialog');
setTimeout(()=>{
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
done();
},1000);
});
组件是应用程序的入口点,通过signup
在url
.
<app-root signup=@signup>
注册会在启动时告诉 Angular 应用程序是否因为用户点击了注册链接而启动。因此,角度可以显示注册是否成功的消息。早些时候我遇到了以下问题(Getting ExpressionChangedAfterItHasBeenCheckedError 错误我从另一个组件更新组件的属性)并解决它,我在应用程序组件中添加setTimeout
了ngAfterViewInit
一个
ngAfterViewInit(){
setTimeout(()=>{
this.checkIfSignupProcess();
this.authGuard.authGuardError$.subscribe((authGuardContext:AuthGuardContext)=>{
this.handleAuthGuardContextMessage(authGuardContext);
});
this.dialogService.dialogMessage$.subscribe((message:DialogServiceMessageContext)=>{
console.log("received message from Dialog box service");
this.handleDialogServiceMessage(message);
})
},100);
/*
OR
this.isSignupProcess(); //this will cause ExpressionChangedAfterItHasBeenCheckedError error s the function changes message of DialogComponent but the change detection isn't complete.
this.cd.detectChanges();
*/
}
更新 2
我尝试使用 'tick' 但测试仍然失败,即使单独运行也是如此。
fit('should show dialog message if the application has unrecognised value of signup attribute in url', ()=>{
jasmine.clock().install();
spyOn(component,'showDialog');
setTimeout(() => {
console.log("in spec's timeout");
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
},1000);
jasmine.clock().tick(1001);
jasmine.clock().uninstall();
/*setTimeout(()=>{
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
done();
},1000);*/
});
失败的原因是Expected spy showDialog to have been called with [ 'Unrecognised message: someIncorrectValue', Function ] but it was never called.
更新 3
我注意到,即使我的组件中的超时值为 100,而我的规范中的超时值为 1000,规范超时首先到期!!!
我的组件中应该显示对话框的代码在我的规范代码之后调用,即使组件中的超时值是 100,而规范中的超时值为 10000!
组件超时
setTimeout(()=>{
console.log("timeout of component");
this.checkIfSignupProcess();
...,100
}
规范的超时
fit('should show dialog message if the application has unrecognised value of signup attribute in url', ()=>{
jasmine.clock().install();
spyOn(component,'showDialog');
setTimeout(() => {
console.log("in spec's timeout 10000");
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
},10000);
jasmine.clock().tick(10001);
jasmine.clock().uninstall();
/*setTimeout(()=>{
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
done();
},1000);*/
});
解决方案
不知道他们为什么会失败,但为了摆脱setTimeout
,您可以尝试组合callThrough
,callFake
如下所示:
it('should show dialog ...', (done)=>{
spyOn(component,'showDialog').and.callThrough().and.callFake(() => {
expect(component.showDialog).toHaveBeenCalledWith("Unrecognised message: someIncorrectValue",jasmine.any);
done();
});
});
推荐阅读
- javascript - 如何使用 vue.js 和 d3.js 加载 csv 文件
- javascript - 如何使 Material UI React 组件中的按钮粘在底部?
- angular - 使用 Angular 时不呈现引导图像和元素
- python - '命令错误退出状态 1' 在 python 中安装 mysql 客户端时收到此错误消息
- vue.js - Gridsome plugin-google-analytics 跟踪从未出现在 GA 平台上
- sql-server-data-tools - VS 2019 dacpac 文件不会让我选择禁止引用警告。任何建议如何解决?
- fb-hydra - 如何在 hydra 中进行文件覆盖?
- c# - 无法加载文件或程序集“Microsoft.VisualStudio.Threading,版本=16.8.0.0
- sql-server - Access 2007 请求 SQL Server 日期和时间
- android-studio - 从“Cold Boot Now”启动时,Android Emulator 恢复到上次状态