reactjs - 开玩笑测试 useInterval React Hook 不起作用
问题描述
试图测试自定义 useInterval Hook 但 jest.advanceTimersByTime(199);
似乎 jest.advanceTimersToNextTimer(1);
没有工作。
我在任何地方登录jest.getTimerCount()
,它返回 0;
自定义挂钩:
import { useRef, useEffect } from 'react';
function useInterval(callback: () => void, delay: number | null) {
const savedCallback = useRef<() => void | null>();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
});
// Set up the interval.
useEffect(() => {
function tick() {
console.log("here"); // This never gets logged !!!!
if (typeof savedCallback?.current !== 'undefined') {
console.log(delay, savedCallback);
}
}
if (delay !== null) {
const id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
export default useInterval;
测试:
import useInterval from "./useInterval";
import { renderHook } from '@testing-library/react-hooks';
describe("useInterval Hook:", () => {
let callback = jest.fn();
beforeAll(() => {
// we're using fake timers because we don't want to
// wait a full second for this test to run.
jest.useFakeTimers();
});
afterEach(() => {
callback.mockRestore();
jest.clearAllTimers();
});
afterAll(() => {
jest.useRealTimers();
});
test('should init hook with delay', () => {
const { result } = renderHook(() => useInterval(callback, 5000));
expect(result.current).toBeUndefined();
expect(setInterval).toHaveBeenCalledTimes(1);
expect(setInterval).toHaveBeenCalledWith(expect.any(Function), 5000);
});
test('should repeatedly calls provided callback with a fixed time delay between each call', () => {
const { result } = renderHook(() => useInterval(callback, 200));
expect(callback).not.toHaveBeenCalled();
// fast-forward time until 1s before it should be executed
jest.advanceTimersByTime(199);
expect(callback).not.toHaveBeenCalled(); // FAILS
// jest.getTimerCount() here returns 0
// fast-forward until 1st call should be executed
jest.advanceTimersToNextTimer(1);
expect(callback).toHaveBeenCalledTimes(1);
// fast-forward until next timer should be executed
jest.advanceTimersToNextTimer();
expect(callback).toHaveBeenCalledTimes(2);
// fast-forward until 3 more timers should be executed
jest.advanceTimersToNextTimer(3);
expect(callback).toHaveBeenCalledTimes(5);
});
});
解决方案
我通过移动jest.useFakeTimers();
到beforeEach
块而不是beforeAll
.
推荐阅读
- azure-pipelines - 如何在 arm 模板中使用 Concat 和 arm 模板部署任务
- signalr - 保持 Angular 8 toast/snackbar 为长时间运行的任务保持活力
- javascript - 取消编辑功能在 Vue 组件中不起作用
- mongodb - MongoDB在读取时将时间戳转换为本地时区
- python - 使用来自另一个数据帧的字符串从 Pandas 数据帧获取索引
- javascript - Netflify CMS 手动初始化中的环境变量(Gridsome)
- angular - Ionic 4 Refresher 没有传入 refresher 对象,所以我无法完成它
- javascript - 在星期六的重力形式日期选择器上显示警报
- python - pytorch 复制权重仅适用于冒号
- r - 如何在r中将平面回归变为曲面?