Angular 角度测试-滴答不响';如果定时器处于组件初始化状态,则无法工作 问题:
我如何让Angular 角度测试-滴答不响';如果定时器处于组件初始化状态,则无法工作 问题:,angular,typescript,testing,timer,Angular,Typescript,Testing,Timer,我如何让勾选开始工作,或者至少如何让测试提前10秒,以便在我的组件中正确调用提交 注意:我不想做等待新的承诺(r=>setTimeout(r,10000))因为它会让我的测试运行得很长,而测试应该很短 目标 我希望submit仅在组件创建10秒后调用cb 描述 我的组件中有一个计时器,它在10秒后完成。此计时器将主题从false更改为true,并用于确定提交组件中的数据是否有效 在测试中,tick似乎根本没有提前定时器,实际上它运行了整整10秒。我试图通过在每个之前的中放置一个fakeAsync
勾选
开始工作,或者至少如何让测试提前10秒,以便在我的组件中正确调用提交
注意:我不想做等待新的承诺(r=>setTimeout(r,10000))
因为它会让我的测试运行得很长,而测试应该很短
目标
我希望submit
仅在组件创建10秒后调用cb
描述
我的组件中有一个计时器,它在10秒后完成。此计时器将主题从false更改为true,并用于确定提交组件中的数据是否有效
在测试中,tick
似乎根本没有提前定时器,实际上它运行了整整10秒。我试图通过在每个之前的中放置一个fakeAsync
来修复此问题,但没有成功创建组件
我试过的
- 在测试组件init中使用
fakeAsync
,以及测试
- 仅在测试中使用
fakeAsync
- 使用
setTimeout(()=>this.obs.next(true),10_000)
代替计时器
- 使用
empty().pipe(延迟(10000)).subscribe(()=>this.obs.next(true))代码>而不是计时器
- 将
计时器
放入ngOnInit
而不是构造函数
- 将
计时器
置于构造函数中,而不是ngOnInit
观察
如果您调整此代码
timer(10_000).subscribe(()=>this.testThis$.next(true));
而是这样
计时器(10_000).订阅(()=>{
调试器;
this.testThis$.next(true)
});
您会发现,每次测试运行时,Dev工具中的Javascript调试器都会在组件创建10秒后触发(如果勾选成功,则不会立即触发)
代码
这是密码。底部是指向GitHub上最小复制的链接
//组件代码
从“@angular/core”导入{Component,OnInit,Inject};
从“rxjs”导入{BehaviorSubject,Subject,timer};
从“rxjs/operators”导入{first,filter};
@组成部分({
选择器:“应用程序勾选测试”,
templateUrl:“./tick test.component.html”,
样式URL:['./勾选test.component.scss']
})
导出类TickTestComponent实现OnInit{
公共测试此$:主题;
建造师(
@注入('TICK_CALLBACK')私有只读cb:()=>void,
) {
this.testThis$=新行为主体(false);
计时器(10_000).subscribe(()=>this.testThis$.next(true));
}
public ngOnInit():void{
}
公共提交():无效{
//10秒后调用回调
这个,测试这个$
.pipe(第一个(),过滤器(a=>!!a))
.subscribe(()=>this.cb());
}
}
//测试代码
/**
*这一次的问题是,我希望“滴答”能提高效率
*在构造函数中创建的计时器的时间,但它不工作
*/
从“@angular/core/testing”导入{async,ComponentFixture,TestBed,tick,fakeAsync};
从“./tick test.component”导入{tick testcomponent};
描述('TickTestComponent',()=>{
let组件:TickTestComponent;
let夹具:组件夹具;
让我们回拨:茉莉花。间谍;
beforeach(异步(()=>{
callback=jasmine.createSpy('TICK_callback');
TestBed.configureTestingModule({
供应商:[
{提供:'TICK_CALLBACK',useValue:CALLBACK},
],
声明:[TickTestComponent]
})
.compileComponents();
}));
在每个之前(()=>{
fixture=TestBed.createComponent(TickTestComponent);
组件=fixture.componentInstance;
fixture.detectChanges();
});
它('应该创建',()=>{
expect(component.toBeTruthy();
});
它('在10秒后应为true',fakeAsync(()=>{
勾选(10_001);
component.submit();
expect(callback).toHaveBeenCalled();
}));
});
最小再生产回购
解决方案
将fixture.detectChanges()
移动到每个测试中,并在那里调用勾选(10_000)
将定时器(10_000).
移动到组件中的ngOnInit
发生了什么事
无论何时使用fakeAsync
都会创建一个代码可以在其中运行的“区域”。根据我的观察,这个区域“存在”,直到它超出范围。通过在每个
之前的中使用fakeAsync
,您会破坏该区域,并且会出现计时器未完成的问题(尽管计时器未完成是理想的结果)
您希望将计时器
移动到ngOnInit
中,因为在调用.createComponent
时不会立即调用它。而是在您第一次运行fixture.detectChanges()
时调用它。因此,当您第一次在测试的fakeAsync
区域内调用fixture.detectChanges()
时,会为您调用ngOnInit
,计时器会在该区域中捕获,您可以按预期控制时间
代码
description('TickTestComponent',()=>{
let组件:TickTestComponent;
let夹具:组件夹具;
让我们回拨:茉莉花。间谍;
beforeach(异步(()=>{
callback=jasmine.createSpy('TICK_callback');
TestBed.configureTestingModule({
供应商:[
{提供:'TICK_CALLBACK',useValue:CALLBACK},
],
声明:[TickTestComponent]
})
.compileComponents();
}));
在每个之前(()=>{
fixture=TestBed.createComponent(TickTestComponent);
组件=fixture.componentInstance;
//不要在这里运行这个
//fixture.detectChanges();
});
它('应该创建',()=>{
expect(component.toBeTruthy();
});
它('在10秒后应为true',fakeAsync(()=>{
//如果这是第一个detectChanges调用,则调用ngOnInit
fixture.detectChanges();
勾选(10_001);
component.submit();
预期(约
describe('TickTestComponent', () => {
let component: TickTestComponent;
let fixture: ComponentFixture<TickTestComponent>;
let callback: jasmine.Spy;
beforeEach(async(() => {
callback = jasmine.createSpy('TICK_CALLBACK');
TestBed.configureTestingModule({
providers: [
{ provide: 'TICK_CALLBACK', useValue: callback },
],
declarations: [ TickTestComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TickTestComponent);
component = fixture.componentInstance;
// don't run this here
// fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should be true after 10s', fakeAsync(() => {
// this calls ngOnInit if it is the first detectChanges call
fixture.detectChanges();
tick(10_001);
component.submit();
expect(callback).toHaveBeenCalled();
}));
});