gpt4 book ai didi

javascript - 当我尝试测试我的重试 util 函数时,jest.advanceTimersByTime 不起作用

转载 作者:行者123 更新时间:2023-12-04 17:20:38 25 4
gpt4 key购买 nike

我有一个我想测试的重试 util 函数。看起来像这样

export const sleep = (t: number) => new Promise((r) => setTimeout(r, t));

type RetryFn = (
fn: Function,
config: {
retryIntervel: number;
retryTimeout: number;
predicate: Function;
onRetrySuccess?: Function;
onRetryFail?: Function;
}
) => Promise<any>;

export const retry: RetryFn = async (
fn,
{ predicate, onRetrySuccess, onRetryFail, retryIntervel, retryTimeout }
) => {
const startTime = Date.now();
let retryCount = 0;
while (Date.now() - startTime < retryTimeout) {
try {
const ret = await fn();
if (predicate(ret)) {
if (retryCount > 0) onRetrySuccess && onRetrySuccess();
return ret;
} else {
throw new Error();
}
} catch {
retryCount++;
}
await sleep(retryIntervel);
}
if (onRetryFail) onRetryFail();
};

它所做的是在给定的时间间隔内重试该函数一段时间。
我以为我可以使用 jest.advanceTimersByTime推进计时器以测试重试发生的次数。
import { retry } from "./index";

const value = Symbol("test");

function mockFnFactory(numFailure: number, fn: Function) {
let numCalls = 0;
return function () {
fn();
numCalls++;
if (numCalls <= numFailure) {
console.log("numCalls <= numFailure");

return Promise.resolve({ payload: null });
} else {
console.log("numCalls => numFailure");

return Promise.resolve({
payload: value
});
}
};
}

describe("retry function", () => {
beforeEach(() => {
jest.useFakeTimers();
});
it("retrys function on 1st attempt, and succeed thereafter", async () => {
const fn = jest.fn();
const onRetrySuccessFn = jest.fn();
const mockFn = mockFnFactory(3, fn);
retry(mockFn, {
predicate: (res: any) => res.payload === value,
onRetrySuccess: onRetrySuccessFn,
retryIntervel: 1000,
retryTimeout: 5 * 60 * 1000
});
jest.advanceTimersByTime(1000);
expect(fn).toHaveBeenCalledTimes(1);
expect(onRetrySuccessFn).not.toHaveBeenCalled();
jest.advanceTimersByTime(1000);
expect(fn).toHaveBeenCalledTimes(2); // 🚨 fail
expect(onRetrySuccessFn).not.toHaveBeenCalled();
jest.advanceTimersByTime(2000);
expect(fn).toHaveBeenCalledTimes(3);// 🚨 fail
expect(onRetrySuccessFn).toHaveBeenCalledTimes(1);
});
});

但似乎没关系 我将计时器提前了多少,该函数只被调用一次。
您可以在 https://codesandbox.io/s/lucid-knuth-e810e?file=/src/index.test.ts 上的代码沙盒上找到代码
但是,有一个已知的 issue使用codesandbox 不断抛出此错误 TypeError: jest.advanceTimersByTime is not a function .此错误不会出现在本地。

最佳答案

这是因为this .
这是我在测试助手文件中使用的内容:

const tick = () => new Promise(res => setImmediate(res));

export const advanceTimersByTime = async time => jest.advanceTimersByTime(time) && (await tick());

export const runOnlyPendingTimers = async () => jest.runOnlyPendingTimers() && (await tick());

export const runAllTimers = async () => jest.runAllTimers() && (await tick());
在我的测试文件中,我导入了我的助手,而不是调用 jest.advanceTimersByTime , 我 await我的 advanceTimersByTime功能。
在您的具体示例中,您只需要 await调用 advanceTimersByTime 后的函数- 像这样:
// top of your test file
const tick = () => new Promise(res => setImmediate(res));

... the rest of your existing test file

jest.advanceTimersByTime(1000);
expect(fn).toHaveBeenCalledTimes(1);
expect(onRetrySuccessFn).not.toHaveBeenCalled();
jest.advanceTimersByTime(1000);
await tick(); // this line
expect(fn).toHaveBeenCalledTimes(2);
expect(onRetrySuccessFn).not.toHaveBeenCalled();
jest.advanceTimersByTime(2000);
await tick(); // this line
expect(fn).toHaveBeenCalledTimes(3)
expect(onRetrySuccessFn).toHaveBeenCalledTimes(1);


关于javascript - 当我尝试测试我的重试 util 函数时,jest.advanceTimersByTime 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66391541/

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