Javascript 在Jest中测试异步代码:未按预期调用done()
这是一个用Jest(v20.0.4)编写的测试套件 前3个测试是预期行为,我的问题与测试4有关Javascript 在Jest中测试异步代码:未按预期调用done(),javascript,unit-testing,jestjs,Javascript,Unit Testing,Jestjs,这是一个用Jest(v20.0.4)编写的测试套件 前3个测试是预期行为,我的问题与测试4有关 test('Test1:列表应该包含7',()=>{ 常量数据=[1,2,7,9]; 期望(数据)。包含(7); }); //>按预期通过 test('Test2:列表应该包含7',()=>{ 常量数据=[1,2,7,9]; expect(数据),contain(8); }); //>按预期失败;需要数组:[1,2,7,9]包含值:8 test('Test3:列表应包含7',(完成)=>{ 函数回
test('Test1:列表应该包含7',()=>{
常量数据=[1,2,7,9];
期望(数据)。包含(7);
});
//>按预期通过
test('Test2:列表应该包含7',()=>{
常量数据=[1,2,7,9];
expect(数据),contain(8);
});
//>按预期失败;需要数组:[1,2,7,9]包含值:8
test('Test3:列表应包含7',(完成)=>{
函数回调(数据){
期望(数据)。包含(7);
完成();
}
设置超时(()=>{
回调([1,2,7,9]);
}, 500);
});
//>按预期通过
test('Test4:列表应包含7',(完成)=>{
函数回调(数据){
expect(数据),contain(8);
完成();
}
设置超时(()=>{
回调([1,2,7,9]);
}, 500);
});
//>失败,错误为“超时-未在指定的超时内调用异步回调”
我的问题是:
在Test4中,done()
在expect
语句之后立即调用。因此,即使expect语句没有通过,我猜它也会失败,错误与Test2类似:
(预期数组:[1,2,7,9]包含值:8)
但是,它失败了,出现了如上所示的超时错误,这表明从未调用done()
为什么??我不明白
有人能引导我通过这种行为吗
我浏览了一下,但找不到任何与此相关的内容。我发现
设置超时
和Jest并不像人们想象的那样有效。但是有一个很好的方法来解决这个问题:
- 在测试开始时,您可以告诉Jest使用Faketimer:
jest.useFakeTimers()代码>
- 当需要执行回调时,可以使用
jest.runAllTimers()触发它代码>
在您的代码中,
expect
调用抛出,而done
永远不会到达。因此,Jest会一直等到它超时并发出您注意到的令人讨厌的、不清楚的错误
解决方案是捕获抛出并调用done(error)
,以向Jest运行程序指示测试失败
test('Test4: the list should contain 7', done => {
function callback(data) {
try {
expect(data).toContain(8);
done();
}
catch (err) {
done(err);
}
}
setTimeout(() => {
callback([1, 2, 7, 9]);
}, 500);
});
运行此操作可获得所需的结果:
Error: expect(received).toContain(expected) // indexOf
Expected value: 8
Received array: [1, 2, 7, 9]
从:
如果expect
语句失败,它将抛出一个错误,并且不会调用done()
。如果我们想在测试日志中看到失败的原因,我们必须将expect
包装在try
块中,并将catch
块中的错误传递到done
。否则,我们将得到一个不透明的超时错误,它不会显示expect(data)
接收到的值
我相信Jest一看到失败的expect语句就会回来。但是关于如何在expect失败后立即调用done()而不是等待超时发生的任何想法。谢谢您的回答。定时器模拟绝对是一个很好的选择。然而,我认为使用“承诺模式”比使用done()的“回调模式”要好,两者都不是“更好”——它们有两个不同的用途。是的,如果您有使用承诺的代码,那么承诺模式会更干净,但有时您希望测试不提供承诺的仅回调函数,在这种情况下,
done
是唯一的选项(除了手动承诺回调)。在OP的代码中,测试在到达done
之前抛出,但解决方案是捕获错误并用它调用done
:done(error)
向Jest发出测试失败的信号。这避免了令人讨厌的超时。