【问题标题】:How to test React useEffect hooks with jasmine and enzyme如何使用 jasmine 和酶测试 React useEffect hooks
【发布时间】:2020-05-07 23:13:21
【问题描述】:

我在测试我的组件时找不到如何调用我的 useEffect 挂钩。

我尝试了几种类似这样的解决方案,但都不起作用:https://reactjs.org/docs/test-utils.html#act

我的组件:

const mapDispatchToProps = (dispatch: IDispatch, ownProps: ITextAreaOwnProps): ITextAreaDispatchProps => ({
        onMount: () => dispatch(addTextArea(ownProps.id)),
});

export const TextArea = (props) => {
        React.useEffect(() => {
            props.onMount();
        }, []);

        // more code... //

        return (
            <>
                <TextareaTagName
                    {...props.additionalAttributes}
                    className={props.className}
                />
                {props.children}
                {getValidationLabel()}
            </>
        );
    };

我的测试:

it('should call prop onMount on mount', () => {
    const onMount = jasmine.createSpy('onMount');

    mount(<TextArea id="textarea-id" onMount={onMount} />);

    expect(onMount).toHaveBeenCalledTimes(1);
});

【问题讨论】:

  • 您可以在上面添加另一个调用。

标签: reactjs testing jasmine react-hooks enzyme


【解决方案1】:

简短的回答是你不能直接测试它。您基本上需要触发组件中的更改检测来激活useEffect 挂钩。您可以通过执行以下操作轻松使用react-dom/test-utils 库

import { act } from 'react-dom/test-utils';
import { shallow, mount } from 'enzyme';

it('should call prop onMount on mount', () => {
  const onMount = jasmine.createSpy('onMount');

  const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);

  act(() => {
    wrapper.update();
  });

  expect(onMount).toHaveBeenCalledTimes(1);
});

【讨论】:

    【解决方案2】:

    测试 onMount 函数调用的方法是调用wrapper.update() 方法。您必须使用酶中的mount,因为shallow 尚不支持调用钩子。更多关于这里的问题 - useEffect not called when the component is shallow rendered #2086

    import { mount } from 'enzyme';
    
    it('should call prop onMount on mount', () => {
      // arrange
      const onMount = jasmine.createSpy('onMount');
      const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
    
      // act
      wrapper.update();
    
      // assert
      expect(onMount).toHaveBeenCalledTimes(1);
    });
    

    如果您在 useEffect 挂钩中进行 api 调用,则必须更新 setTimeout 挂钩中的包装器,以便更改反映在组件上。

    import { mount } from 'enzyme';
    
    it('should call prop onMount on mount', () => {
      // arrange
      const onMount = jasmine.createSpy('onMount');
      const wrapper = mount(<TextArea id="textarea-id" onMount={onMount} />);
    
      setTimeout(() => {
          // act
          wrapper.update();
    
          // assert
          expect(onMount).toHaveBeenCalledTimes(1);
      });
    });
    

    【讨论】:

      【解决方案3】:

      关于文档,useEffect 应该在任何道具更改时更新。

      1. 您可以使用其他道具调用测试。
      2. 可以模拟使用效果。

       /* mocking useEffect */
      useEffect = jest.spyOn(React, "useEffect");
      mockUseEffect(); // 2 times
      mockUseEffect(); //
      
      const mockUseEffect = () => {
             useEffect.mockImplementationOnce(f => f());
        };

      【讨论】:

        猜你喜欢
        • 2020-11-01
        • 1970-01-01
        • 2020-03-24
        • 2021-01-14
        • 2018-04-12
        • 2020-03-20
        • 2020-03-20
        • 2020-12-16
        • 2020-03-23
        相关资源
        最近更新 更多