Jest - 高级测试
在本章中,我们将介绍在 Jest 中测试异步代码。异步任务(如 API 调用、计时器和文件操作)在 JavaScript 中很常见。Jest 提供了简单的方法来测试它们。以下是我们将要介绍的主题:
Jest - 异步测试
异步测试用于测试涉及 API 调用、计时器或文件操作等需要时间才能完成的任务的代码。在 JavaScript 中,常见的异步操作包括:
- setTimeout:延迟代码执行。
- HTTP 请求(使用 fetch 或 axios):等待服务器响应。
- Promise :处理无法立即获得的未来值。
在 Jest 中,异步测试可确保您的测试等待这些任务完成后再进行断言,从而防止过早检查可能导致错误结果。
Jest 支持不同的异步测试方法:
- 基于回调的代码:使用 done() 来表示测试已完成。
- 基于 Promise 的代码:使用 resolves 和 rejections 来测试 Promise 结果。
- Async/Await:一种现代、更简洁的语法,用于处理 Promise ,提高可读性和结构。
Jest - Promise 测试
Promise 表示异步操作的最终结果,要么解决(成功),要么拒绝(失败)。
要测试返回 Promise 的函数,只需从测试中返回 Promise 即可。Jest 将自动等待它解决或拒绝。
测试已解决的 Promise
在测试已解决的 Promise 时,您希望它成功并返回一个值。这可以使用 .then() 或 Jest 的 .resolves 匹配器来完成。
const fetchData = () => Promise.resolve('Data received'); test('fetchData resolves with correct value', () => { return expect(fetchData()).resolves.toBe('Data received'); });
测试被拒绝的 Promise
测试被拒绝的 Promise 时,您预计它会失败并返回错误或拒绝消息。这可以使用 .catch() 或 Jest 的 .rejects 匹配器来完成。
const fetchError = () => Promise.reject('Error occurred'); test('fetchError rejects with correct message', () => { return expect(fetchError()).rejects.toBe('Error occurred'); });
Jest - Async/Await 测试
async 和 await 是 JavaScript 功能,可让您以类似同步的方式编写异步代码。这使代码更具可读性,更易于测试。
在 Jest 中,您可以使用 async 和 await 来测试异步函数,使测试等待 Promise 解决后再继续。
测试异步函数
要测试 异步函数,您可以使用 await。Jest 会自动等待 Promise 解决或拒绝后再进行断言。
const fetchData = async () => 'Data received'; test('fetchData resolves with the correct value', async () => { const data = await fetchData(); expect(data).toBe('Data received'); });
测试抛出错误的异步函数
如果异步函数可能抛出错误,您可以使用await和expect().rejects来测试拒绝。
const fetchError = async () => { throw new Error('Something went wrong'); }; test('fetchError throws an error', async () => { await expect(fetchError()).rejects.toThrow('Something went wrong'); });
使用 expect.assertions()
测试抛出错误的异步函数时,使用 expect.assertions() 确保在测试完成之前完成所有断言。
test('fetchError throws an error', async () => { expect.assertions(1); // 确保至少有一个断言运行 try { await fetchError(); // 调用异步函数 } catch (error) { expect(error).toMatch('Something went wrong'); // 检查错误是否符合预期 } });
将 async/await 与 .resolves 和 .rejects 结合使用>
您可以将 async/await 与 Jest 的 .resolves 和 .rejects 匹配器结合使用,以使您的测试更简洁,并避免手动处理 Promise 。
将 .resolves 与 async/await 结合使用>
test('fetchData resolves with correct value', async () => { await expect(fetchData()).resolves.toBe('Data received'); });
将 .rejects 与 async/await 结合使用
test('fetchError rejects with the correct message', async () => { await expect(fetchError()).rejects.toThrow('Something went wrong'); });
Jest - 回调测试
在 Jest 中测试带有回调的函数时(将函数作为参数传递给其他函数,以便稍后执行),您需要确保测试等待回调被调用后才能完成。
如何在 Jest 中测试回调?
在 Jest 中,您可以使用 done() 函数测试使用回调的异步函数。您将 done 作为参数传递给测试,然后在回调中调用 done() 以让 Jest 知道测试何时完成。
测试回调
假设我们有一个函数 fetchDataFromServer,它接受一个回调并模拟延迟获取数据。
const fetchDataFromServer = (callback) => { setTimeout(() => { callback('Server Response: Success'); }, 1000); // 模拟 1 秒延迟 };
现在,让我们编写一个测试来检查回调是否收到了正确的数据:
test('fetchDataFromServer should return correct data', done => { const callback = (data) => { expect(data).toBe('Server Response: Success'); //检查数据是否正确 done(); // 告诉 Jest 测试已完成 }; fetchDataFromServer(callback); // 使用回调调用函数 });
常见错误:忘记 done()
如果您忘记调用 done(),Jest 将过早完成测试并给出超时错误,因为它不知道测试仍在运行。以下是一个会失败的测试示例:
test('fetchDataFromServer should return correct data', () => { const callback = (data) => { expect(data).toBe('Server Response: Success'); }; fetchDataFromServer(callback); // 测试在回调之前结束得太早 });
这将失败,因为 Jest 在执行回调之前完成了测试,导致超时错误。