Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Jest中测试异步代码:未按预期调用done()_Javascript_Unit Testing_Jestjs - Fatal编程技术网

Javascript 在Jest中测试异步代码:未按预期调用done()

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',(完成)=>{ 函数回

这是一个用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',(完成)=>{
函数回调(数据){
期望(数据)。包含(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发出测试失败的信号。这避免了令人讨厌的超时。