异步测试

异步测试

JavaScript 代码中常常会包含异步代码,当测试异步代码时,Jest 需要知道什么时候异步代码执行完成,在异步代码执行完之前,它会去执行其他的测试代码。Jest 提供了多种方式测试异步代码。

回调函数

当执行到测试代码的尾部时,Jest 即认为测试完成。因此,如果存在异步代码,Jest 不会等待回调函数执行。要解决这个问题,在测试函数中我们接受一个参数叫做 done,Jest 将会一直等待,直到我们调用 done()。如果一直不调用 done(),则此测试不通过。

// async/fetch.js
export const fetchApple = callback => {
  setTimeout(() => callback("apple"), 300);
};

// async/fetch.test.js
import { fetchApple } from "./fetch";

test("the data is apple", done => {
  expect.assertions(1);
  const callback = data => {
    expect(data).toBe("apple");
    done();
  };

  fetchApple(callback);
});

expect.assertions(1) 验证当前测试中有 1 处断言会被执行,在测试异步代码时,能确保回调中的断言被执行。

Promise

如果异步代码返回 Promise 对象,那我们在测试代码直接返回该 Promise 即可,Jest 会等待其 resolved,如果 rejected 则测试不通过。

test("the data is banana", () => {
  expect.assertions(1);
  return fetchBanana().then(data => expect(data).toBe("banana"));
});

如果期望 promise 是 rejected 状态,可以使用 .catch()

test("the fetch fails with an error", () => {
  expect.assertions(1);
  return fetchError().catch(e => expect(e).toMatch("error"));
});

除此之外,还可以使用上文中提到的 .resolves.rejects

Async/Await

如果异步代码返回 promise,我们还可以使用 async/await:

test("async: the data is banana", async () => {
  expect.assertions(1);
  const data = await fetchBanana();
  expect(data).toBe("banana");
});

test("async: the fetch fails with an error", async () => {
  expect.assertions(1);
  try {
    await fetchError();
  } catch (e) {
    expect(e).toMatch("error");
  }
});

也可以将 aysnc/awiat 与 .resolves.rejects 结合:

test("combine async with `.resolves`", async () => {
  expect.assertions(1);
  await expect(fetchBanana()).resolves.toBe("banana");
});
上一页