Jon*_*old 4 testing timer typescript angular
我该如何开始tick工作,或者至少如何让测试提前 10 秒以正确调用submit我的组件?
注意:我不想这样做,await new Promise(r => setTimeout(r, 10000))因为这会让我的测试运行很长,而测试应该很短
我只想在组件创建 10 秒后submit调用cb
我的组件中有一个计时器,它在 10 秒后完成。该定时器将主题由假变为真,用于判断组件中提交数据是否有效。
在测试中,tick计时器似乎根本没有提前,实际上运行了整整 10 秒。我试图通过在创建组件时添加一个来解决这个问题,fakeAsync但beforeEach没有成功。
fakeAsync,以及测试fakeAsync仅在测试中使用setTimeout(() => this.obs.next(true), 10_000)而不是计时器empty().pipe(delay(10000)).subscribe(() => this.obs.next(true));而不是计时器timer代替ngOnInit构造函数timerin 构造函数而不是ngOnInit如果你调整这段代码
timer(10_000).subscribe(() => this.testThis$.next(true));
Run Code Online (Sandbox Code Playgroud)
改为这样
timer(10_000).subscribe(() => {
debugger;
this.testThis$.next(true)
});
Run Code Online (Sandbox Code Playgroud)
您会发现,每次运行测试时,开发工具中的 Javascript 调试器都会在组件创建后 10 秒被触发(而不是在勾选有效时立即触发)。
这是代码。底部是 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());
}
}
Run Code Online (Sandbox Code Playgroud)
// 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();
}));
});
Run Code Online (Sandbox Code Playgroud)
fixture.detectChanges()每个测试,并tick(10_000)在那里打电话。timer(10_000)...到ngOnInit组件中每当您使用fakeAsync代码可以在其中运行的“区域”时,就会创建一个“区域”。根据我的观察,这个区域“存在”直到超出范围。通过使用fakeAsyncin beforeEach,您会破坏该区域,并且会遇到计时器未完成的问题(尽管计时器未完成是理想的结果)。
您希望将 移入timer,ngOnInit因为它不会在调用时立即调用.createComponent。相反,它会在您fixture.detectChanges()第一次运行时被调用。因此,当您第一次fixture.detectChanges()在测试区域内调用时,系统会为您调用,计时器将在区域中捕获,您可以按预期控制时间。fakeAsyncngOnInit
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();
}));
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2890 次 |
| 最近记录: |