【发布时间】:2020-10-01 17:51:58
【问题描述】:
问题
如何让tick 工作,或者至少如何让测试提前 10 秒以在我的组件中适当地调用 submit?
注意:我不想做await new Promise(r => setTimeout(r, 10000)),因为它会使我的测试运行很长时间,而测试应该很短
目标
我希望 submit 仅在创建组件后 10 秒后调用 cb
说明
我的组件中有一个计时器,它在 10 秒后完成。此计时器将主题从 false 更改为 true,并用于确定在组件中提交数据是否被视为 有效。
在测试中,tick 似乎根本没有提前计时器,它实际上运行了整整 10 秒。我试图通过在 beforeEach 中添加 fakeAsync 来解决此问题,但该组件无济于事。
我尝试过的
- 在测试组件初始化以及测试中使用
fakeAsync - 仅在测试中使用
fakeAsync - 使用
setTimeout(() => this.obs.next(true), 10_000)代替计时器 - 使用
empty().pipe(delay(10000)).subscribe(() => this.obs.next(true));代替计时器 - 将
timer放入ngOnInit而不是构造函数 - 将
timer放入构造函数而不是ngOnInit
观察
如果你调整这个代码
timer(10_000).subscribe(() => this.testThis$.next(true));
改为这样
timer(10_000).subscribe(() => {
debugger;
this.testThis$.next(true)
});
您会发现,每次运行测试时,Dev Tools 中的 Javascript 调试器都会在组件创建后 10 秒触发(而不是在 tick 有效时立即触发)。
代码
这是代码。底部是 GitHub 上最小复制的链接。
// component code
import { Component, OnInit, Inject } from '@angular/core';
import { BehaviorSubject, Subject, timer } from 'rxjs';
import { first, filter } from 'rxjs/operators';
@Component({
selector: 'app-tick-test',
templateUrl: './tick-test.component.html',
styleUrls: ['./tick-test.component.scss']
})
export class TickTestComponent implements OnInit {
public testThis$: Subject<boolean>;
constructor(
@Inject('TICK_CALLBACK') private readonly cb: () => void,
) {
this.testThis$ = new BehaviorSubject<boolean>(false);
timer(10_000).subscribe(() => this.testThis$.next(true));
}
public ngOnInit(): void {
}
public submit(): void {
// call the callback after 10s
this.testThis$
.pipe(first(), filter(a => !!a))
.subscribe(() => this.cb());
}
}
// test code
/**
* The problem in this one is that I am expecting `tick` to advance the
* time for the timer that was created in the constructor, but it is not working
*/
import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';
import { TickTestComponent } from './tick-test.component';
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;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should be true after 10s', fakeAsync(() => {
tick(10_001);
component.submit();
expect(callback).toHaveBeenCalled();
}));
});
最小复制回购
【问题讨论】:
标签: angular typescript testing timer