【问题标题】:Jest can't perform a React state update on an unmounted component + react state updates should be wrapped into actJest 无法对未安装的组件执行 React 状态更新 + 应将反应状态更新包装到 act 中
【发布时间】:2021-12-31 15:50:38
【问题描述】:

所以我正在尝试测试表单输入。首先表单应该显示一个错误,然后在输入一个值后,用户单击一个按钮,错误应该被删除。
我想我明白为什么会发生这种情况,但我不知道如何测试此功能。

我有条件地呈现错误消息并更新状态,所以我知道这可能就是为什么它告诉我将我的测试包装在 act() 中。我还告诉模拟服务器发送一个错误状态,我想可能是因为我覆盖了初始处理程序,它只会响应我定义的错误状态。这也不行。

由于我是测试新手,因此我不确定如何测试。非常感谢任何帮助。

这里是测试函数:

it('clears validation error after username field is updated', async () => {
  let validationError;
  server.use(generateValidationError('username', 'Username cannot be null'));
  setup();

  await act(async () => {
    userEvent.click(button);
    validationError = await screen.findByText('Username cannot be null');
    userEvent.type(usernameInput, 'username001');
    userEvent.click(button);
    expect(validationError).not.toBeInTheDocument();
  });
});

【问题讨论】:

    标签: javascript reactjs unit-testing jestjs


    【解决方案1】:

    由于在组件中设置状态或异步执行某些操作可能需要“一些时间”,因此您应该将您的情况视为潜在的类似 Promise 的情况。

    为确保您的测试始终等待发生的任何更改,您可以使用waitFor 方法并在代码中添加回调函数来检查某些状态。这是来自React Testing library

    it('clears validation error after username field is updated', async () => {
      let validationError;
      server.use(generateValidationError('username', 'Username cannot be null'));
      setup();
    
      await act(async () => {
        userEvent.click(button);
        userEvent.type(usernameInput, 'username001');
        userEvent.click(button);
    
        await waitFor(async () => {
          validationError = await screen.findByText('Username cannot be null');
          expect(validationError).not.toBeInTheDocument();
        });
      });
    });
    

    提示
    当您声明包含 DOM 元素的内容时,请始终在执行某些操作后选择该元素(单击按钮后更改您的案例中的验证状态)。

    在上面的代码中,我根据上述提示更改了该选择器的位置。

    【讨论】:

      【解决方案2】:

      就方法而言,我会:

      1. 测试错误最初是否可见
      2. 点击按钮
      3. 测试错误已消失

      如果您要使用act(),通常将断言放在其函数体之外,请参阅https://reactjs.org/docs/testing-recipes.html#act

      我什至不确定您是否需要act()。官方测试库文档中的示例似乎可以满足您的需求:

      【讨论】:

        【解决方案3】:

        真是个愚蠢的错误。 我遇到的第一个错误是因为我在成功提交后隐藏了我的表单。因此该组件将卸载,然后我将无法对其进行测试。我想出了一个解决方法,分别测试每个字段并确保它没有成功提交表单。

        通过修复上述错误,我不再需要使用 act(),因为我没有收到任何开玩笑的错误。之后测试顺利通过。

        it.each`
              field         | message                      | label
              ${'username'} | ${'Username cannot be null'} | ${'Username'}
              ${'email'}    | ${'Email cannot be null'}    | ${'Email'}
              ${'password'} | ${'Password cannot be null'} | ${'Password'}
            `(
              'clears validation error after $field field is updated',
              async ({ field, message, label }) => {
                server.use(generateValidationError(field, message));
                setup();
                userEvent.click(button);
                const validationError = await screen.findByText(message);
                const inputByLabel = screen.getByLabelText(label);
                userEvent.type(
                  inputByLabel,
                  label === 'Email' ? 'user@testuser.com' : 'username001'
                );
                //this line was needed to stop the form from submitting
                userEvent.type(confirmPasswordInput, 'newpassword');
                userEvent.click(button);
                await waitFor(() => {
                  expect(validationError).not.toBeInTheDocument();
                });
              }
            );
        

        【讨论】:

          猜你喜欢
          • 2019-10-19
          • 2020-11-17
          • 2023-02-11
          • 2020-08-02
          • 2019-11-09
          • 2019-05-30
          • 2021-05-30
          相关资源
          最近更新 更多