【问题标题】:useFakeTimers not working in jest/testing-libraryuseFakeTimers 在 jest/testing-library 中不起作用
【发布时间】:2022-02-21 13:37:36
【问题描述】:

我正在渲染一个使用 setTimeout 将内部文本从加载状态更改为所需消息的元素:

function Message({ message }: any) {
  const [showMessage, setShowMessage] = useState(false);

  useEffect(() => {
    const CTATimer = setTimeout(() => {
      setShowMessage(true);
    }, 1500);
    return () => {
      clearTimeout(CTATimer);
    };
  }, []);

  if (!showMessage) {
    return <p>Loading...</p>;
  }

  return (
    <>
      <div>{message.text}</div>
    </>
  );
}

相应的测试呈现,然后将时间提前 1500 毫秒,然后应该显示消息。但是,目前测试失败,终端显示文本仍然是Loading...。测试是这样写的:

const mockMessage = {
  text: "this is a message",
  answers: [],
  id: 1,
};

afterEach(() => {
  jest.useRealTimers();
});

it("should show message after setTimeout", () => {
  jest.useFakeTimers();
  jest.advanceTimersByTime(1500);
  customRender(<Message message={mockMessage} />); // my customRender is just the default render but with a ThemeProvider wrapper.
  const message = screen.getByText(/this is a message/i);
  expect(message).toBeInTheDocument();
});

为什么我的测试在 1500 毫秒后仍然呈现加载状态?

【问题讨论】:

    标签: javascript reactjs react-hooks jestjs react-testing-library


    【解决方案1】:

    您应该在渲染组件后提前计时器。此外,您应该在act 函数中调用jest.advanceTimersByTime()。否则会抛出警告:Warning: An update to Message inside a test was not wrapped in act(...).

    index.tsx:

    import React from 'react';
    import { useEffect, useState } from 'react';
    
    export function Message({ message }: any) {
      const [showMessage, setShowMessage] = useState(false);
    
      useEffect(() => {
        const CTATimer = setTimeout(() => {
          setShowMessage(true);
        }, 1500);
        return () => {
          clearTimeout(CTATimer);
        };
      }, []);
    
      if (!showMessage) {
        return <p>Loading...</p>;
      }
    
      return (
        <>
          <div>{message.text}</div>
        </>
      );
    }
    

    index.test.tsx:

    import React from 'react';
    import { render, screen, act } from '@testing-library/react';
    import '@testing-library/jest-dom/extend-expect';
    import { Message } from './';
    
    describe('Message', () => {
      const mockMessage = {
        text: 'this is a message',
        answers: [],
        id: 1,
      };
    
      afterEach(() => {
        jest.useRealTimers();
      });
    
      it('should show message after setTimeout', () => {
        jest.useFakeTimers();
        render(<Message message={mockMessage} />);
        act(() => {
          jest.advanceTimersByTime(1500);
        });
        const message = screen.getByText(/this is a message/i);
        expect(message).toBeInTheDocument();
      });
    });
    

    测试结果:

     PASS  stackoverflow/71174071/index.test.tsx (9.705 s)
      Message
        ✓ should show message after setTimeout (27 ms)
    
    -----------|---------|----------|---------|---------|-------------------
    File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    -----------|---------|----------|---------|---------|-------------------
    All files  |     100 |      100 |     100 |     100 |                   
     index.tsx |     100 |      100 |     100 |     100 |                   
    -----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        10.903 s
    Ran all test suites related to changed files.
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 2020-02-10
    • 2021-03-22
    相关资源
    最近更新 更多