如何使用 React 测试库测试 HOC

时间:2021-02-05 16:15:08

标签: javascript reactjs react-testing-library higher-order-components

我有一个 HOC,向组件添加了一些道具,用于处理网络请求并将数据作为道具传递。以下是 HOC 的一个非常简化的版本:

export const withTags = (Component) => {
  class WithTags extends PureComponent {
    getItems() {
      return getTags({
            search: this.state.searchTerm
          })
        .then((items) => this.setState({
          items
        }));
    }

    .
    .
    .

    render() {
      return (
        <Component
          {...this.props}
          items={this.state.items}
          getItems={this.getItems}
        />
      );
    }
  }

  return withTags;
}

使用 enzyme 我可以轻松地执行以下操作:

    it('should return tags', async () => {
      const mockComponent = jest.fn(() => null);
      const WithTagsComponent = withTags(mockComponent);

      const wrapper = shallow(<WithTagsComponent />);
      const res = await wrapper.props().getItems();

      expect(res).toEqual(getTagsResponseMock);
      expect(tagsApi.getTags).toHaveBeenCalledTimes(1);
      expect(tagsApi.getTags).toHaveBeenCalledWith({
        limit: PAGE_SIZE,
      });
      expect(wrapper.props().items).toEqual([tagFlowMock]);
    });

但是这种方法在 React 测试库中不起作用,因为我们应该从最终用户的角度进行测试,而不是访问 props。那么,我应该如何使用 React 测试库来测试这样的 HOC?

1 个答案:

答案 0 :(得分:0)

我认为您的测试几乎可以正常工作,但您需要替换两件事。 由于您在此处手动调用 getItems,因此您可以创建一个模拟组件,该组件理想情况下可以执行与您计划与 HOC 一起使用的组件类似的操作。 例如,这个模拟组件可能有一个按钮,当点击该按钮时会调用 getItems 并且还会显示 items

const MockComponent = ({items, getItems}) => { 
  return (
    <div>
      <button data-testid="button" onClick={getItems}>Click me</button>
      <ul>
        { items.map((item, index) => <li key={index}>{item}</li>) }
      </ul>
    </div>
  )

然后在您的测试中而不是手动调用 getItems

const res = await wrapper.props().getItems();

你可以做类似的事情

fireEvent.click(getByTestId('button')

然后断言您的 tagsApi 被调用并且您的组件显示正确的项目。

相关问题