测试异步代码

为你的测试返回一个Promise,则Jest会等待Promise的resove状态 If the promise is rejected, the test will fail.

For example, let’s say that fetchData returns a promise that is supposed to resolve to the string 'peanut butter'. 我们可以使用下面的测试代码︰

或者,您可以在测试中使用 asyncawait。 写异步测试用例时,可以在传递给test的函数前面加上async。 例如,可以用来测试相同的 fetchData 方案︰

  1. test('the data is peanut butter', async () => {
  2. const data = await fetchData();
  3. expect(data).toBe('peanut butter');
  4. });
  5. test('the fetch fails with an error', async () => {
  6. expect.assertions(1);
  7. try {
  8. } catch (e) {
  9. expect(e).toMatch('error');
  10. }
  11. });

你也可以将 async and await.resolves or .rejects一起使用。

上述示例中, and await实际上是一种基于Promise的异步语法糖。

caution

如果期望Promise被Reject,则需要使用 .catch 方法。 请确保添加 expect.assertions 来验证一定数量的断言被调用。 否则,一个fulfilled状态的Promise不会让测试用例失败。

  1. test('the fetch fails with an error', () => {
  2. expect.assertions(1);
  3. return fetchData().catch(e => expect(e).toMatch('error'));
  4. });

If you don’t use promises, you can use callbacks. For example, let’s say that fetchData, instead of returning a promise, expects a callback, i.e. fetches some data and calls callback(null, data) when it is complete. 你期望返回的数据是一个字符串 'peanut butter'

默认情况下,一旦到达运行上下文底部Jest测试立即结束。 这样意味着这个测试将不能按预期工作。

问题在于一旦fetchData执行结束,此测试就在调用回调函数前结束了(因为同步代码结束后,才是异步拿到的数据)。

还有另一种形式的 test 可以解决这个问题。 使用单个参数调用 done,而不是将测试放在一个空参数的函数。 Jest会等done回调函数被调用执行结束后,再结束测试。

  1. test('the data is peanut butter', done => {
  2. function callback(error, data) {
  3. if (error) {
  4. done(error);
  5. return;
  6. try {
  7. done();
  8. } catch (error) {
  9. done(error);
  10. }
  11. }
  12. fetchData(callback);
  13. });

expect 执行失败,它会抛出一个错误,后面的 done() 不再执行。 若我们想知道测试用例为何失败,我们必须将 expect 放入 try 中,将 error 传递给 catch 中的 done函数。 否则,最后控制台将显示一个超时错误失败,不能显示我们在 expect(data) 中接收的值。

注意: done() 不应与Promises混合,因为这会导致您测试中的内存泄漏。

您还可以使用 .resolves 匹配器在您期望的声明,Jest 会等待这一 Promise 来解决。 如果 Promise 被拒绝,则测试将自动失败。

一定不要忘记把整个断言作为返回值返回⸺如果你忘了return语句的话,在 fetchData 返回的这个 promise 变更为 resolved 状态、then() 有机会执行之前,测试就已经被视为已经完成了。

如果你希望Promise返回rejected,你需要使用 .rejects 匹配器。 它和 .resolves 匹配器是一样的使用方式。 如果 Promise 被拒绝,则测试将自动失败。

  1. test('the fetch fails with an error', () => {
  2. });