【问题标题】:Testing with useEffect and jest.useFakeTimer()使用 useEffect 和 jest.useFakeTimers() 进行测试
【发布时间】: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(),但似乎它并没有真正起作用。

有人知道如何在这里修复测试吗?

【问题讨论】:

    标签: javascript react-native jestjs


    【解决方案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);
      });
    });
    

    【讨论】:

      猜你喜欢
      • 2023-02-10
      • 2021-08-18
      • 2020-01-31
      • 2021-03-08
      • 1970-01-01
      • 2020-05-07
      • 2020-12-16
      • 2011-05-31
      • 2017-02-18
      相关资源
      最近更新 更多