gpt4 book ai didi

javascript - 如何用 jest 为在 javascript 中实现的指数退避重试方法编写单元测试

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

尝试测试通过获取重试 API 请求 5 次的指数退避方法,将有以下延迟:[1 毫秒、10 毫秒、100 毫秒、1 秒、10 秒],我无法成功测试它.

方法

export const delay = retryCount => new Promise(resolve => setTimeout(resolve, 10 ** retryCount));

/**
* Fetching with delay when api call fails,
* first 5 retries will have the following delays: [1 ms, 10 ms, 100 ms, 1 s, 10 s]
*/
export const fetchRetry = async (options, retryCount = 0, lastError = null) => {
if (retryCount > 5) throw new Error(lastError);
try {
return await fetch(options);
} catch (error) {
await delay(retryCount);
return fetchRetry(options, retryCount + 1, error);
}
};

测试

import fetchMock from 'jest-fetch-mock';

import { delay, fetchRetry } from './retry';

// This can be set up globally if needed
fetchMock.enableMocks();

beforeEach(() => {
fetch.resetMocks();
});

describe('fetchWithExponentialBackoffRetry', () => {
it('fetch is called once when response is 200', done => {
fetch.mockResponseOnce(
JSON.stringify({
success: true,
message: 'OK',
code: 200,
data: 'c86e795f-fe70-49be-a8fc-6876135ab109',
}),
);

setTimeout(function() {
fetchRetry({
inventory_type_id: 2,
advertiser_id: 2315,
file: null,
});
expect(fetch).toHaveBeenCalledTimes(1);
done();
}, 0);
});

it('fetch is called 5 times when response is returns failure', done => {
fetch.mockReject(() => Promise.reject(new Error('Rejected')));

setTimeout(function() {
fetchRetry({
inventory_type_id: 2,
advertiser_id: 2315,
file: null,
});
expect(fetch).toHaveBeenCalledTimes(5);
done();
}, 100000);
});
});

我收到以下错误

console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29错误:错误:连接ECONNREFUSED 127.0.0.1:8

我认为它必须执行 delay 方法我必须以某种方式将 setTimeout 合并到我的测试中,现在确定如何在这里模拟它。我将不胜感激。

最佳答案

您正在测试异步函数的结果,因此您也需要使测试异步 - 您没有这样做 - 即您没有等待 fetchRetry因此只是调用done()同步。

认为错误是由使用 setTimeout 引起的这里。这看起来像是一个竞争条件错误,如果不调试就很难确定,但从阅读代码来看,问题似乎是你在 mock fetchjest-fetch-mock ,但是由于您的测试代码同步运行并且您有...

beforeEach(() => {
fetch.resetMocks();
});

...它可能正在取消设置 fetch在首先运行的测试中调用之前进行模拟,因此它实际上是在调用您的 API - 因此出现错误。

使测试异步非常简单 - docs are here - 使用 async/await 它甚至更干净,因为您实际上不需要使用 done - 当 promise 解决(或拒绝)时,测试就完成了。

基本上你的测试代码大部分是一样的,除了你会是await调用 fetchRetry ,像这样:

it('fetch is called once when response is 200', async () => {
fetch.mockResponseOnce(...)

await fetchRetry({ ... })
expect(fetch).toHaveBeenCalledTimes(1);
});

it('fetch is called 5 times when response is returns failure', async () => {
fetch.mockReject(...);

try {
await fetchRetry({ ... });
} catch (err) {
// eventual error expected as response failure is mocked
expect(fetch).toHaveBeenCalledTimes(5);
}
});

关于javascript - 如何用 jest 为在 javascript 中实现的指数退避重试方法编写单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63380768/

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