很抱歉,回复晚了,但我只设法检查了您的答案,并且通过强制创建一个 prop 来覆盖 axios,我发现上述解决方案有点 hacky,所以我在下面详细介绍了您的问题的可能解决方案。我没有根据您在下面发布的 git 链接来确定这一点,因为看起来可能会导致混乱。
我们使用 await waitFor 非常重要,以确保我们可以在调用 Promise 之前和之后侦听对 busy 所做的更新,这样它就不会触发 Warning: An update to TestHook inside a test was not wrapped in act(...) 警告。
我认为该消息对用户有点欺骗性,因为用户通常认为将所述问题包装在一个行为中会解决问题,但在这种情况下,问题实际上在于使用 setInterval 并且它能够更新状态。
希望我的解决方案对您有所帮助,并努力弃用 axiosOverrideProp。
使用PollingHook.js
import * as React from 'react';
import requestAdaptor from './requestAdaptor';
export function usePollingHook(pollTimeMs = 2000) {
const [busy, setBusy] = React.useState(false);
const [isPolling, setPolling] = React.useState(false);
const [data, setData] = React.useState(null);
React.useEffect(() => {
if (isPolling) {
const poll = async () => {
if (!busy) {
setBusy(true);
const resp = await requestAdaptor();
setBusy(false);
setData(resp);
}
};
const interval = setInterval(poll, pollTimeMs);
return () => clearInterval(interval);
}
return () => null;
}, [isPolling, busy, setBusy, pollTimeMs]);
return {
data,
busy,
isPolling,
setPolling,
};
}
index.spec.js
import { act, renderHook } from '@testing-library/react-hooks';
import { usePollingHook } from './usePollingHook';
import requestAdaptor from './requestAdaptor';
jest.useFakeTimers();
jest.mock('./requestAdaptor', () => jest.fn().mockResolvedValue(1));
describe('usePollingHook', () => {
it('returns default props', () => {
const { result } = renderHook(() => usePollingHook());
expect(result.current.data).toEqual(null);
expect(result.current.busy).toEqual(false);
expect(result.current.isPolling).toEqual(false);
expect(result.current.setPolling).toEqual(expect.any(Function));
});
it('ensures the state is updated when the hook has polled a request', async (done) => {
const { result, waitFor } = renderHook(() => usePollingHook());
expect(result.current.busy).toEqual(false);
act(() => {
result.current.setPolling(true);
});
await waitFor(() => expect(result.current.isPolling).toEqual(true));
act(() => {
jest.advanceTimersByTime(10000);
});
await waitFor(() => expect(result.current.busy).toEqual(true));
expect(requestAdaptor).toBeCalled();
await waitFor(() => expect(result.current.busy).toEqual(false));
expect(result.current.data).toEqual(1);
done();
});
});
requestAdaptor.js
一些伪造的 http 函数,它会包装一个承诺,例如模拟axios或者fetch
export function requestAdaptor() {
return new Promise((resolve) => {
return setTimeout(() => {
return resolve({ userId: 1 });
}, 1000);
});
}
export default requestAdaptor;