使用 useState 和 setTimeout 测试组件

Test a component with useState and setTimeout

代码结构如下:

FunctionComponent.js

...
const [open, handler] = useState(false);
setTimeout(() => {handler(true);}, 2000);
...
return (
...
<div className={active ? 'open' : 'close'}>
)

comp.test.js

jest.useFakeTimers();

test('test case 1', () => {
 expect(wrapper.find('open').length).toBe(0);
 jest.advanceTimersByTime(2000);
 <b>expect(wrapper.find('open').length).toBe(1);</b>
 jest.useRealTimers();
});

问题是测试中粗体写的表达式表示open class的长度仍然是0,所以实际和预期不符。

您想测试钩子的结果而不是钩子本身,因为这就像测试 React。您实际上想要一个测试,检查打开的 class 是否存在然后不存在(反之亦然),看起来您正在尝试。

简而言之,要解决您的问题,您需要在选择 class 时使用 ".open"。我还建议使用 .exists() 检查 class 而不是 ".length()" 然后你也可以使用 ".toBeTruthy()"

您也可以考虑改进以 Jest/Enzyme combined 格式编写测试:

import { shallow } from 'enzyme';
import { FunctionComponent } from './FunctionComponent.jsx';

jest.useFakeTimers();

describe('<FunctionCompnent />', () => {
  const mockProps = { prop1: mockProp1, prop2: mockProp2, funcProp3: jest.fn() };
  const wrapper = shallow(<FunctionComponent {...mockProps} />);

  afterEach(() => {
   jest.advanceTimersByTime(2000);
  });

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

  it('should render as closed initially', () => {
    expect(wrapper.find('.close').exists()).toBeTruthy();
    // you could also add the check for falsy of open if you wanted
    // expect(wrapper.find('.open').exists()).toBeFalsy();
  });

  it('should change to open after 2 seconds (or more)', () => {
    expect(wrapper.find('.open').exists()).toBeTruthy();
    // you could also add the check for falsy of close if you wanted
    // expect(wrapper.find('.close').exists()).toBeFalsy();
  });
});

编辑:抱歉,我再次检查你的代码后发现我把测试写反了,现在应该修复了。