gpt4 book ai didi

javascript - 如何使用JEST测试递归函数的时程

转载 作者:搜寻专家 更新时间:2023-10-30 21:56:03 24 4
gpt4 key购买 nike

我使用 JEST 编写了一个测试。我不知道如何在 JEST 中测试 promise 递归。

在这个测试中,执行递归的重试函数是测试的目标,直到 promise 被解决。

export function retry<T>(fn: () => Promise<T>, limit: number = 5, interval: number = 1000): Promise<T> {
return new Promise((resolve, reject) => {
fn()
.then(resolve)
.catch((error) => {
setTimeout(() => {
// Reject if the upper limit number of retries is exceeded
if (limit === 1) {
reject(error);

return;
}
// Performs recursive processing of callbacks for which the upper limit number of retries has not been completed
try {
resolve(retry(fn, limit - 1, interval));
} catch (err) {
reject(err);
}
}, interval);
});
});
}

对上述重试函数进行如下测试。

  1. retry() 在第三次运行时解决。第一次、第二次、第三次分别每1000秒调用一次。

我以为用JEST写这些的时候会是这样


jest.useFakeTimers();

describe('retry', () => {
// Timer initialization for each test
beforeEach(() => {
jest.clearAllTimers();
});
// Initialize timer after all tests
afterEach(() => {
jest.clearAllTimers();
});

test('resolve on the third call', async () => {
const fn = jest
.fn()
.mockRejectedValueOnce(new Error('Async error'))
.mockRejectedValueOnce(new Error('Async error'))
.mockResolvedValueOnce('resolve');

// Test not to be called
expect(fn).not.toBeCalled();
// Mock function call firs execution
await retry(fn);
// Advance Timer for 1000 ms and execute for the second time
jest.advanceTimersByTime(1000);
expect(fn).toHaveBeenCalledTimes(2);
// Advance Timer for 1000 ms and execute for the third time
jest.advanceTimersByTime(1000);
expect(fn).toHaveBeenCalledTimes(3);

await expect(fn).resolves.toBe('resolve');
});

});

结果报以下错误失败

● retry › resolve on the third call
Timeout - Async callback was not invoked within the 30000ms timeout specified by jest.setTimeout.Error:

> 16 | test('resolve on the third call', async () => {
| ^
17 | jest.useFakeTimers();
18 | const fn = jest
19 | .fn()

关于这个错误,我认为在 JEST 的设置中是可以管理的。但是,从根本上说,我不知道如何在 JEST 中测试 promise 递归处理。

最佳答案

你的函数很难用定时器测试。

当您调用 await retry(fn); 时,这意味着您将等待直到 retry 返回一个值,但是 setTimeout 已被阻止直到你调用 jest.advanceTimersByTime(1000); => 这是主要原因,因为 jest.advanceTimersByTime(1000); 从未被调用过。

你可以看到我的例子,它与 jest 的假计时器一起工作得很好。

  test("timing", async () => {
async function simpleTimer(callback) {
await callback();
setTimeout(() => {
simpleTimer(callback);
}, 1000);
}

const callback = jest.fn();
await simpleTimer(callback); // it does not block any things
for (let i = 0; i < 8; i++) {
jest.advanceTimersByTime(1000); // then, this line will be execute
await Promise.resolve(); // allow any pending jobs in the PromiseJobs queue to run
}
expect(callback).toHaveBeenCalledTimes(9); // SUCCESS
});

我想,你可以跳过测试计时器的细节,只测试你的逻辑:fn 被调用了 3 次,最后它返回 "resolve"

test("resolve on the third call", async () => {
const fn = jest
.fn()
.mockRejectedValueOnce(new Error("Async error"))
.mockRejectedValueOnce(new Error("Async error"))
.mockResolvedValueOnce("resolve");

// expect.assertions(3);

// Test not to be called
expect(fn).not.toBeCalled();
// Mock function call firs execution

const result = await retry(fn);

expect(result).toEqual("resolve");

expect(fn).toHaveBeenCalledTimes(3);
});

注意:删除所有假计时器 - jest.useFakeTimers

关于javascript - 如何使用JEST测试递归函数的时程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56124733/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com