什么时候需要将“rerender”与React测试库一起使用?

rob*_*ear 9 javascript reactjs redux react-testing-library

在过去,我和我的同事通常会为主父组件编写 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
);
Run Code Online (Sandbox Code Playgroud)

然后我开始编写典型的 RTL 代码以使Alerts组件完成其任务。其中之一是单击将触发ADD_ALERT操作的按钮。我单步执行了所有代码,Redux 减速器显然在新警报下正常工作,正如我所预期的那样,但回到组件中Alerts,它question.alerts仍然存在null,而在生产代码中,它肯定是在新警报下正确更新的。

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

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

我尝试了这个,这似乎是一个解决方案。我不完全理解为什么我必须这样做,并认为我应该联系社区,看看是否有一种方法可以避免使用rerender.

Jos*_*ley 4

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

或者,如果您知道触发事件后应发生特定的 DOM 更改,则可以使用waitFor. React 测试库介绍中的一个示例:

  render(<Fetch url="/greeting" />)

  fireEvent.click(screen.getByText('Load Greeting'))

  await waitFor(() => screen.getByRole('alert'))
Run Code Online (Sandbox Code Playgroud)