Javascript 如何使用jasmine测试使用setInterval的angular服务?
我正在尝试设置setInterval调用的测试。setInterval始终会创建一个新计时器,因此无论您向前移动多远,tick()始终会出现以下错误消息: 错误:队列中仍有1个计时器 如果我用setInterval覆盖setTimeout函数,那么测试将按预期通过。我使用公共属性myTimerFunc(通常设置为setInterval)添加了代码,以允许我的angular服务使用该属性。测试代码将其设置为setTimeout 有没有更好的方法来测试setInterval? 如果jasmine可以忽略队列中的最后一个计时器,那就太好了。这样我就可以不用额外的拐杖来测试了 例如,除非取消对覆盖setInterval的行的注释,否则此代码将失败。我不介意在测试代码中这样做,但我确实希望避免在普通代码中添加额外的内容来允许这种覆盖Javascript 如何使用jasmine测试使用setInterval的angular服务?,javascript,angular,timer,jasmine,Javascript,Angular,Timer,Jasmine,我正在尝试设置setInterval调用的测试。setInterval始终会创建一个新计时器,因此无论您向前移动多远,tick()始终会出现以下错误消息: 错误:队列中仍有1个计时器 如果我用setInterval覆盖setTimeout函数,那么测试将按预期通过。我使用公共属性myTimerFunc(通常设置为setInterval)添加了代码,以允许我的angular服务使用该属性。测试代码将其设置为setTimeout 有没有更好的方法来测试setInterval? 如果jasmine可以
import{fakeAsync,tick}来自“@angular/core/testing”
描述('测试设置超时和设置间隔:',()=>{
它('setTimeout应该工作',fakeAsync(()=>{
让callback=jasmine.createSpy('setTimeoutCallback')
设置超时(()=>{
回调函数()
}, 55)
勾选(56)
expect(callback).toHaveBeenCalled();
}));
//设setInterval=setTimeout
它('setInterval应该工作',fakeAsync(()=>{
让callback=jasmine.createSpy('setTimeoutCallback')
设置间隔(()=>{
回调函数()
}, 55)
勾选(56)
expect(callback).toHaveBeenCalled();
}));
})
如果将setInterval
包装到一个服务中,您可以模拟该服务,并且一切都是确定的,没有副作用。基本上你会做一些类似的事情
class IntervalService {
setInterval(callback: () => void, interval: number) {
return setInterval(callback, interval);
}
clearInterval(intervalId: number) {
clearInterval(intervalId);
}
}
class MockIntervalService {
callback;
setInterval(callback: () => any, interval: number) {
this.callback = callback;
return 1;
}
clearInterval(interval: number) {
callback = undefined;
}
tick() {
callback();
}
}
你可以通过这样的方式来嘲笑它
class IntervalService {
setInterval(callback: () => void, interval: number) {
return setInterval(callback, interval);
}
clearInterval(intervalId: number) {
clearInterval(intervalId);
}
}
class MockIntervalService {
callback;
setInterval(callback: () => any, interval: number) {
this.callback = callback;
return 1;
}
clearInterval(interval: number) {
callback = undefined;
}
tick() {
callback();
}
}
然后在测试中,您可以通过调用模拟服务上的勾选
来控制间隔。最好的一点是,一切都是同步的,这使得测试更容易推理
注入服务需要一些额外的工作,但我不认为这是一个很大的负担。一些关于FakeAsync的理论,flush:,这将帮助您理解问题 通过使用fakeAsync,我们可以确保在测试中进行断言之前,所有异步代码都已运行,并且我们甚至可以对如何在整个测试中推进时间进行微调控制
- 当测试在fakeAsync区域内运行时,我们可以使用两个名为flushMicrotasks和tick的函数。tick函数将时间提前指定的毫秒数,因此tick(100)将执行100ms内发生的任何异步任务。flushMicrotasks函数将清除队列中当前的所有微任务。简而言之,如果您不确定时间或依赖于promise/settimeout,那么您需要使用flush()方法
it('should test some async code', fakeAsync(() => {
let flag = false;
setTimeout(() => { flag = true; }, 100);
expect(flag).toBe(false); // PASSES
tick(50);
expect(flag).toBe(false); // PASSES
tick(50);
expect(flag).toBe(true); // PASSES
}));
其他可能的备选方案:
it('should test some asynccode', fakeAsync(() => {
let flag = false;
setTimeout(() => { flag = true; }, 100);
expect(flag).toBe(false);
flushMicrotasks();
expect(flag).toBe(true); // FAILS
}));
在您的场景中
flush()可以用了谢谢。我同意你的建议不是很大的负担,特别是因为我正在考虑限制setInterval的重复次数(而不是让它离开服务器)