【问题标题】:react library testing are not updating my screen反应库测试没有更新我的屏幕
【发布时间】:2021-03-10 13:34:19
【问题描述】:

我最近遇到了这个奇怪的问题。我正在使用react-testing-library 并尝试进行简单的更新。每当用户输入正确的名称时,他们将获得 10 分,并将记录在屏幕上。但是,目前没有记录新分数(我保持默认分数为 0),并且我还收到错误消息: Cannot log after tests are done. Did you forget to wait for something async in your test? Attempted to log "Warning: An update to Pokemon inside a test was not wrapped in act(...).

这就是我的测试代码的样子

//PokemonPage.test.js
test.only("should have their score updated if they guess the name correctly", async () => {
    const guessedPokemon = "Pikachu";
    jest.spyOn(global, "fetch").mockResolvedValue({
      json: () =>
        Promise.resolve({
          name: "Pikachu",
          sprites: {
            other: {
              "official-artwork": {
                front_default:
                  "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/25.png",
              },
            },
          },
        }),
    });
    render(<Pokemon pokemonTrainer={pokemonTrainer} />);
    expect(screen.getByText(/Score: 0/)).toBeInTheDocument();
    await waitFor(() => screen.findByRole("img"));
    userEvent.type(await screen.findByRole("textbox"), guessedPokemon);
    await waitFor(() => userEvent.click(screen.getByRole("button")))
    expect(screen.getByText(/Score: 10/)).toBeInTheDocument()
  });

这是它应该调用的代码:

//PokemonPage.js
const handleChange = (e) => setValue(e.target.value);

  const handleSubmit = async (e) => {
    e.preventDefault();
    pokemonRef.current = await getPokemon();
    setPokemonList((prev) => [
      ...prev,
      { name: pokemonRef.current.name, image: pokemonRef.current.image },
    ]);
    updateScore(value)
    setValue('')
  };

  const updateScore = async (guessedPokemonName) => {
    if (guessedPokemonName === pokemonList[pokemonList.length - 1].name) {
       setPokemonTrainerObject(prev => ({...prev, score: pokemonTrainerObject['score'] + 10 || 10 }))
    } 
  };

基本上我正在提交用户输入,如果它是正确的guessedPokemonName === pokemonList[pokemonList.length - 1].name,那么用户对象将更新分数。这就是我试图用我的测试来模拟的。

我曾尝试使用waitFor,希望代码明白组件需要更新但无济于事。

有没有人遇到过类似的情况?

【问题讨论】:

    标签: javascript unit-testing testing jestjs react-testing-library


    【解决方案1】:

    来自 React 的警告“警告:测试中 Pokemon 的更新未包含在 act(...) 中”意味着它检测到您的状态发生了未在测试中考虑的更改。

    在这种情况下,此警告包含在更说明性的消息中,说明此问题发生在您的测试之后。

    在您的代码中,您有await waitFor(() =&gt; userEvent.click(screen.getByRole("button")))。但是,waitFor 旨在与断言一起使用。换句话说,它意味着等到期望为真——而不是直到触发事件,因为像这样的事件的触发不是异步的(它的处理可能是,但不是触发它。)

    相反,您应该只触发该事件,然后然后 waitFor 可以测试的东西表明该过程已完成。例如,您说“他们将获得 10 分,并将记录在屏幕上”。因此,在您的活动结束后,请执行 waitFor 以查找显示他们正确回答的消息,您已经在下一行中执行此操作。

    那就试试吧:

    userEvent.click(screen.getByRole("button"));
    await waitFor(() => {
       expect(screen.getByText(/Score: 10/)).toBeInTheDocument();
    });
    

    或者,甚至更简单,因为 findBy* 方法在内部使用 waitFor

    userEvent.click(screen.getByRole("button"));
    await screen.findByText(/Score: 10/);
    

    PS 你可以通过阅读 Kent Dodds 的文章了解更多关于该错误消息和一些不同的修复方法,Fix the "not wrapped in act() warning

    【讨论】:

    • 谢谢先生!效果很好!似乎我误解了测试工具的工作方式。我认为按钮将是我解决我的承诺的地方。再次感谢!
    • 太好了,很高兴听到。请“接受”答案,以便其他人知道它解决了您的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 2022-11-13
    • 2021-03-21
    • 2014-12-05
    相关资源
    最近更新 更多