【问题标题】:When is it necessary to use `rerender` with the React Testing Library?什么时候需要在 React 测试库中使用 `rerender`?
【发布时间】:2021-05-10 08:38:42
【问题描述】:

过去,我和我的同事通常会为主要的父组件编写 React 测试库 (RTL) 测试,这些组件通常有许多嵌套的子组件。该测试是有意义的并且运行良好。顺便说一句,有问题的子组件非常专用于该父组件,而不是可重用的种类。

但现在我们正在尝试为每个组件编写 RTL 测试。今天我正在尝试为Alerts 组件构建测试,它是Alert 组件的父级,距离顶级组件大约4 级。这是我的测试文件中的一些示例代码:

function renderDom(component, store) {
  return {
    ...render(<Provider store={store}>{component}</Provider>),
    store,
  };
}

let store = configureStore(_initialState);
const spy = jest.spyOn(store, 'dispatch');
const { queryByTestId, queryByText, debug } = renderDom(
  <Alerts question={store.getState().pageBuilder.userForm.steps[0].tasks[0].questions[1]} />,
  store
);

然后我开始编写典型的 RTL 代码来让 Alerts 组件完成它的工作。其中之一是单击将触发ADD_ALERT 操作的按钮。我单步执行了所有代码,Redux reducer 显然按照我的意图在新警报下正常工作,但回到 Alerts 组件中,question.alerts 仍然是 null 而在生产代码中它肯定会被更新正确使用新警报。

我与一位同事交谈,他说对于这种类型的测试,我需要像这样人为地重新渲染组件:

rerender(<Provider store={store}><Alerts question={store.getState().pageBuilder.userForm.steps[0].tasks[0].questions[1]} /></Provider>);

我试过这个,它似乎是一个解决方案。我不完全明白为什么我必须这样做,我想我会联系社区,看看是否有办法避免使用rerender

【问题讨论】:

    标签: javascript reactjs redux react-testing-library


    【解决方案1】:

    如果不查看更多代码,很难确定,但我使用 RTL 的典型方法是采用模拟单击按钮的 fireEvent 调用并将其包装在 act 调用中。这应该会导致 React 完成处理来自您的事件的任何事件、更新状态、重新渲染等。

    或者,如果您知道触发事件会导致特定的 DOM 更改,您可以使用waitFor。来自React Testing Library intro 的示例:

      render(<Fetch url="/greeting" />)
    
      fireEvent.click(screen.getByText('Load Greeting'))
    
      await waitFor(() => screen.getByRole('alert'))
    

    【讨论】:

      猜你喜欢
      • 2021-04-15
      • 1970-01-01
      • 2021-06-16
      • 2012-09-16
      • 1970-01-01
      • 2017-06-17
      • 2015-12-02
      • 2012-10-29
      相关资源
      最近更新 更多