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 中,您可以使用 asyncawait 来测试异步函数,使测试等待 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');
});

测试抛出错误的异步函数

如果异步函数可能抛出错误,您可以使用awaitexpect().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 。

.resolvesasync/await 结合使用>

test('fetchData resolves with correct value', async () => {
    await expect(fetchData()).resolves.toBe('Data received');
});

.rejectsasync/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 在执行回调之前完成了测试,导致超时错误。