首页 > 解决方案 > 在useEffect()中状态更改后酶mount()重新渲染?

问题描述

我是 React 和 React 单元测试的新手。我有一个组件,它根据使用状态设置的状态加载一些 div。在 useEffect 中,如果一个函数返回一个被拒绝的 promise,那么应该显示一个错误 div。我想测试这个场景,但是因为初始状态设置为 error = false,所以仍然显示原始 div。

我的问题是,我该怎么做才能让测试注册更新的 div?我正在使用 Enzyme 的 mount(),但我也尝试过使用 shallow()。我还验证了它实际上是通过一些 console.logs 进入 .catch() 的。

零件:

export const Main = (props) => { 
  const [showLoadError, setShowLoadError] = useState(false);
  const [loadError, setLoadError] = useState('');

  React.useEffect(() => {
    const { categories, actions } = props;

    // retrieve categories from Db if they don't exist in state
    if (categories.length === 0) {
      actions.loadCategories().catch(err => {
        setShowLoadError(true);
        setLoadError(err.message);
      })
    } else {
      setShowLoadError(false);
      setLoadError('');
    }
  }, []);

  return (

    <>
      {/* conditional show for error container if loading failed */}
      {showLoadError &&
        <div className="load-error">
          Error loading categories. {loadError}
        </div>
      }
      {/* conditional show for no Load error */}
      {!showLoadError &&
        <div className="grid-container grid-container--fit">
          <div><CategoryContainer /></div>
          <div><ItemContainer /></div>
          <div><FileAssociationsContainer /></div>
        </div>
      }
    </>
  );
}

测试:

import React from 'react';
import ConnectedApp, { Main } from './Main';
import { shallow, mount } from 'enzyme';

jest.mock("../category/CategoryContainer");
jest.mock("../item/ItemContainer");
jest.mock("../fileAssociations/FileAssociationsContainer");

describe("Main component", () => {

  beforeEach(() => {
    fetch.resetMocks()
  });

  test('should render error div after loadCategories fail',  () => {
    const categories = [];
    const errMessage = {message: 'test error'}
    const actions = {
      loadCategories: jest.fn(() => {
        return Promise.reject(errMessage);
      })
    };

    const wrapper = mount(<Main categories={categories} actions={actions} />);

    wrapper.setProps(); // rerenders

    // expect there to be a load-error div
    expect(wrapper.find('div').hasClass('load-error')).toBe(true)

    // expect loadCategories to be called because component was passed in empty categories
    expect(actions.loadCategories).toBeCalled();

  });



});

我已经尝试过了wrapper.setProps()wrapper.update()在我没有运气之前。

此外,这个单元测试给出了一个开玩笑的警告,即An update to Main inside a test was not wrapped in act(...). 仅当 actions.loadCategories() 返回拒绝的承诺时才会发生这种情况。当它返回一个已解决的承诺时,它不会这样做。我尝试将代码移动到 act() 中,但没有成功删除错误,如下所示:

act(() => {
      actions = {
        loadCategories: jest.fn(() => {
          return Promise.reject(errMessage);
        })
      };
      wrapper = mount(<Main categories={categories} actions={actions} />);
      wrapper.setProps(); // rerenders
    });

标签: javascriptreactjsunit-testingjestjsenzyme

解决方案


推荐阅读