问题描述
尝试测试通过提取5次重试API请求的指数补偿方法,将具有以下延迟:[1 ms,10 ms,100 ms,1 s,10 s],我无法成功测试
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,});
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
,因此只是在调用{{1 }}同步。
我认为该错误是由于此处使用done()
引起的。这看起来像是一个竞态条件错误,很难在不调试的情况下确定,但是从阅读代码来看,问题似乎是您正在用setTimeout
来模拟fetch
,但是由于测试代码是同步运行的你有...
jest-fetch-mock
...这可能是在首先运行的测试中进行调用之前取消beforeEach(() => {
fetch.resetMocks();
});
模拟的设置,因此它实际上是在调用您的API-因此出错。
使测试异步非常简单-docs are here-使用async / await甚至更干净,因为您实际上不需要使用fetch
-测试只是在promise解析后完成(或拒绝)。
基本上,您的测试代码将基本相同,不同的是,您将done
调用await
,就像这样:
fetchRetry