React中用Sinon/Jest假定时器测试setInterval调用失败问题
解决React假定时器测试setInterval和函数调用的问题
我来帮你搞定这个测试难题!你的问题主要出在假定时器的启用时机、setInterval的Mock方式以及组件挂载与Spy的顺序上,咱们一步步修正:
问题根源分析
- 假定时器生效太晚:你先渲染了组件再调用
jest.useFakeTimers(),这时候componentDidMount已经用真实定时器执行了,假定时器完全没起作用。 - setInterval未被Mock:直接检查
setInterval的调用次数会报错,因为它不是Jest的mock函数,需要先对它进行Spy或者Mock。 - Spy与组件挂载顺序错误:如果先渲染组件再Spy
checkIdleTime,组件初始化时的函数调用不会被捕获到。
修正后的完整测试代码
import { shallow } from 'enzyme'; import PureMain from './PureMain'; // 假设authTimeoutSeconds是你定义的变量,示例设为5 const authTimeoutSeconds = 5; describe('PureMain idle check', () => { let checkIdleTimeSpy; let setIntervalSpy; let wrapper; beforeEach(() => { // 1. 先启用假定时器,确保组件挂载时使用的是假定时器 jest.useFakeTimers(); // 2. Spy全局的setInterval,捕获它的调用行为 setIntervalSpy = jest.spyOn(window, 'setInterval'); // 3. 提前Spy组件的checkIdleTime方法,确保能捕获初始化时的调用 checkIdleTimeSpy = jest.spyOn(PureMain.prototype, 'checkIdleTime'); // 4. 最后再渲染组件 wrapper = shallow(<PureMain />); }); afterEach(() => { // 清理Spy和假定时器,避免影响其他测试用例 jest.restoreAllMocks(); jest.useRealTimers(); }); it('should check the idle time after [authTimeoutSeconds] seconds of inactivity', () => { // 验证setInterval是否按预期调用 expect(setIntervalSpy).toHaveBeenCalledTimes(1); expect(setIntervalSpy).toHaveBeenCalledWith( expect.any(Function), authTimeoutSeconds * 1000 ); // 快进所有待处理的定时器,触发checkIdleTime调用 jest.runAllTimers(); // 验证checkIdleTime是否被执行 expect(checkIdleTimeSpy).toHaveBeenCalledTimes(1); // 验证定时器实例的超时时间是否正确 const idleCheckTimeout = wrapper.instance().state.idleCheck; expect(idleCheckTimeout).not.toBeNull(); expect(idleCheckTimeout._idleTimeout).toBe(authTimeoutSeconds * 1000); }); });
关键修正点说明
- 假定时器先启用:
jest.useFakeTimers()必须在组件渲染前调用,这样组件componentDidMount里的setInterval才会使用Jest的假定时器。 - Mock全局setInterval:通过
jest.spyOn(window, 'setInterval')监视全局定时器函数,就能正常验证它的调用次数和参数了。 - Spy时机提前:在渲染组件前就Spy
PureMain.prototype.checkIdleTime,确保组件初始化时的函数调用能被捕获。 - 清理测试环境:在
afterEach里恢复所有Mock和真实定时器,防止不同测试用例之间互相干扰。
如果你的Jest版本是27+,可以尝试用jest.runOnlyPendingTimers()替代jest.runAllTimers(),避免触发不必要的递归定时器(如果存在的话)。
内容的提问来源于stack exchange,提问作者Mzq
相关产品推荐
相关产品推荐

