【问题标题】:Test functionality with timeouts in react-testing-library and jest在 react-testing-library 和 jest 中使用超时测试功能
【发布时间】:2022-02-09 02:24:56
【问题描述】:

我正在尝试关注 TDD,我有一个 span,它应该会在 5 秒后出现在屏幕上。我根本没有实现跨度,所以测试应该失败,但目前它通过了测试expect(messageSpan).toBeInTheDocument

这是我的两个测试:

it("doesn't show cta message at first", () => {
    render(<FAB />);
    const messageSpan = screen.queryByText(
      "Considering a career in nursing? Join our team!"
    );
    expect(messageSpan).toBeNull(); // passes, as it should
  });

  it("should show the cta message after 5 secs", () => {
    render(<FAB />);
    setTimeout(() => {
      const messageSpan = screen.getByText( // also tried queryByText instead of get
        "Considering a career in nursing? Join our team!"
      );
      expect(messageSpan).toBeInTheDocument(); // also passes, even though messageSpan should throw an error.
    }, 5000);
  });

这是我的FAB 组件,您可以在其中看到根本没有消息:

export default function FAB() {
  return (
// using styled-components; there's no content in any of these.
    <StyledFABContainer>
      <StyledFABButton>
        <BriefcaseIcon />
      </StyledFABButton>
    </StyledFABContainer>
  );
}

为了使事情复杂化,我不打算设置我调用setTimeout 的函数。我将在 5 秒的设定时间后简单地设置状态。所以不要认为我可以使用 jest 文档的计时器模拟部分中的建议:https://jestjs.io/docs/timer-mocks

我的两个问题是:

a) 为什么这会通过而不抛出错误/空值? b) 如何正确测试 RTL 中的setTimeout 功能?

更新:尝试使用useFakeTimersactwaitFor 等的各种组合,但没有运气。这是我当前写出的测试,并抛出两个错误 - 一个说我需要在更改状态时使用act(我现在是,但仍然如此),另一个说我的messageSpan 为空:

it("cta message to display after 5 secs", async () => {
    jest.useFakeTimers();
    const el = document.createElement("div");
    act(() => {
      ReactDOM.render(<FAB />, el);
    });
    jest.advanceTimersByTime(5000);
    const messageSpan = screen.queryByText(
      "Considering a career in nursing? Join our team!"
    );
    expect(messageSpan).toBeInTheDocument();
  });

【问题讨论】:

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


    【解决方案1】:

    您不能在测试中像这样使用 setTimeout。一个明显的原因是您不想在测试中等待 5 秒再继续。想象一个在 10 分钟后会发生变化的组件。你不能等那么久,但应该改用笑话mocked timers API。 您可以推进 nodejs 计时器,以便您的组件更改,然后立即做出断言。 关于您编写​​的测试的其他评论:

    • 如果您正在等待更改,您应该使用测试库中的 await waitFor(() => ...)。默认情况下,它每 50 毫秒检查一次期望值,总共 5 秒。如果所有期望都通过了,它会继续。您应该在那里进行异步断言。
    • “expect(messageSpan).toBeNull()”应该是“expect(messageSpan).not.toBeInTheDocument()”。最好使用测试库提供的可访问性方式。

    【讨论】:

    • 我尝试了waitFor,但运气不佳。我还尝试使用act,因为我的终端在我的useEffect 中抱怨我的更新状态而不使用act。我也尝试过使用假计时器并将时间提前 5000 毫秒。不幸的是,它们都不起作用。用这个新代码更新了我的问题。
    猜你喜欢
    • 2021-02-11
    • 2020-03-22
    • 2020-05-14
    • 2021-02-28
    • 2020-01-20
    • 1970-01-01
    • 2019-07-08
    • 1970-01-01
    相关资源
    最近更新 更多