在react-testing-library和jest中使用超时测试功能

cre*_*lus 5 unit-testing reactjs jestjs react-testing-library

我正在尝试遵循 TDD,并且span5 秒后应该会出现在屏幕上。我根本没有实现跨度,所以测试应该失败,但目前它通过了测试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);
  });
Run Code Online (Sandbox Code Playgroud)

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

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

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

我的两个问题是:

a) 为什么这个会通过并且不会抛出错误/null?b) 如何正确测试setTimeoutRTL 中的功能?

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

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);
  });
Run Code Online (Sandbox Code Playgroud)

Chr*_*lus 0

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

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