异步测试
异步测试
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");
});