使用 useEffect 和 jest.useFakeTimers() 进行测试
Posted
技术标签:
【中文标题】使用 useEffect 和 jest.useFakeTimers() 进行测试【英文标题】:Testing with useEffect and jest.useFakeTimer() 【发布时间】:2019-09-25 05:25:03 【问题描述】:我正在尝试在这里创建简单的复习组件
Refresher.js
import useEffect from 'react';
const Refresher = ( onRefresh ) =>
useEffect(() =>
const id = setInterval(onRefresh, 60000);
return () =>
clearInterval(id);
;
, [onRefresh]);
return null;
;
export default Refresher;
但是,当我尝试使用 jest.useFakeTimers()
对其进行测试时,不知何故它不起作用。即使在jest.runOnlyPendingTimers()
之后也不会调用存根
import React from 'react';
import renderer from 'react-test-renderer';
import Refresher from '../Refresher';
describe('Refresher', () =>
test('should refresh the result every 60 seconds', () =>
jest.useFakeTimers();
const onRefreshSpy = jest.fn();
const refresher = renderer.create(<Refresher onRefresh=onRefreshSpy />);
expect(onRefreshSpy).not.toHaveBeenCalled();
jest.runOnlyPendingTimers();
refresher.update(); // Trying force update here
expect(onRefreshSpy).toHaveBeenCalled();
);
);
如果没记错的话,如果组件没有更新,间隔将不会运行,所以我尝试使用refresher.update()
,但似乎它并没有真正起作用。
有人知道如何在这里修复测试吗?
【问题讨论】:
【参考方案1】:您只需要模拟 useLayoutEffect 而不是 useEffect。见问题here
describe('Refresher', () =>
beforeAll(() => jest.spyOn(React, 'useEffect').mockImplementation(React.useLayoutEffect))
test('should refresh the result every 60 seconds', () =>
jest.useFakeTimers();
const onRefreshSpy = jest.fn();
const refresher = renderer.create(<Refresher onRefresh=onRefreshSpy />);
expect(onRefreshSpy).not.toHaveBeenCalled();
jest.runOnlyPendingTimers();
expect(onRefreshSpy).toHaveBeenCalled();
);
);
【讨论】:
太棒了!这很有帮助,它可以与额外的afterEach
清理一起工作,但似乎这不是测试useEffect
的好方法,希望我们能有一个合适的解决方案【参考方案2】:
您可以更好地控制modern
假计时器。
import React from 'react';
import renderer from 'react-test-renderer';
import Refresher from '../Refresher';
describe('Refresher', () =>
test('should refresh the result every 60 seconds', () =>
jest.useFakeTimers('modern'); // default for Jest 27+
const onRefreshSpy = jest.fn();
const refresher = renderer.create(<Refresher onRefresh=onRefreshSpy />);
expect(onRefreshSpy).not.toHaveBeenCalled();
jest.advanceTimersByTime(60000);
expect(onRefreshSpy).toHaveBeenCalledTimes(1);
jest.advanceTimersByTime(60000);
expect(onRefreshSpy).toHaveBeenCalledTimes(2);
);
);
【讨论】:
以上是关于使用 useEffect 和 jest.useFakeTimers() 进行测试的主要内容,如果未能解决你的问题,请参考以下文章
使用 React Native 和 useEffect 获取
使用 useEffect 和 setInterval 一个接一个地打印一个字母