【发布时间】:2021-05-29 04:07:47
【问题描述】:
我有一个想要测试的重试实用程序功能。看起来是这样的
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.tshttps://codesandbox.io/s/lucid-knuth-e810e?file=/src/index.test.tscodesandbox 上找到代码
但是,有一个已知的 issue 带有代码框,它不断抛出此错误 TypeError: jest.advanceTimersByTime is not a function 。此错误不会在本地出现。
【问题讨论】:
-
看起来它的问题在于它抛出
Error: jest.advanceTimersByTime is not a function的 codesandox 出现了一个问题 github.com/codesandbox/codesandbox-client/issues/513
标签: javascript typescript unit-testing jestjs