酶和玩笑测试在setTimeout之后更新状态的React应用

时间:2019-04-13 17:52:50

标签: reactjs unit-testing timeout jestjs enzyme

我正在使用enzymejest测试一个应用,该应用在挂载后一定时间后会更新stateDOM(使用setTimout()) 。但是,如何确定时间已经过去并执行检查?

我尝试使用jest.advanceTimersByTime(),但它给了我警告。 Warning: An update to %s inside a test was not wrapped in act(...). 所以我只是这样做了,但仍然没有任何改变。

const someComponents = () => {
  return (<div className="child"></div>);
}

const App = () => {
  const [remove, setRemove] = useState(false);
  setTimeout(() => setRemove(true), 5000);
  return (
    <div className="App">
      { remove &&
         <someComponent/>
      }
    </div>
  );
};

关于我的测试:

import React from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';

describe('test', () => {
  it('should remove child at end of timer', () => {
    const wrapper = mount(<App />);
    expect(wrapper.find('.child')).toHaveLength(1);

    act(() => {
      jest.advanceTimersByTime(1000000);

      wrapper.update(); //Do I need this?
      console.log(wrapper.debug())// Still shows child in DOM
      expect(wrapper.find('.child')).toHaveLength(0);
    });
  };
}

5秒后someComponent应该已经卸载,但是在我尝试对其进行测试时仍然存在。另外,访问removesetRemove的正确方法是什么用酵素?将enzymereact hooks一起使用的信息很少。

1 个答案:

答案 0 :(得分:0)

似乎存在一个问题,即当前的测试库(目前)无法正确处理useEffect,因此测试将始终失败。您可以找到当前跟踪的问题here

附带说明,您的钩子示例需要使用useEffect才能起作用。

import React, { useState, useEffect } from "react";

const Example = () => <div className="child">child</div>;

const App = () => {
  const [showChild, setShowChild] = useState(true);
  useEffect(() => {
    const timer = setTimeout(() => setShowChild(false), 5000);

    return () => {
      clearTimeout(timer);
    };
  }, []);

  return <div className="App">{showChild && <Example />}</div>;
};

export default App;

工作示例

Edit Hook Timer


也就是说,一种解决方法是暂时使用类

这是一个展示钩子问题的本地示例和一个工人阶级的示例https://github.com/mattcarlotta/hooks-versus-classes

要安装:

  • 打开终端到您的桌面。
  • 键入git clone git@github.com:mattcarlotta/hooks-versus-classes.git并输入。
  • 键入cd hooks-versus-classes
  • 键入yarn installnpm install
  • 键入yarn testnpm run test来运行测试(它们全部通过,但是one会抛出console.error,并且断言为不是功能正常)。
  • 键入yarn devnpm run dev来运行项目。

工作类代码示例:

App.js

import React, { Component } from 'react';

const Example = () => <div className="child">child</div>;

class App extends Component {
  state = { showChild: true };

  componentDidMount = () => this.setTimer(); // setup timeout on mount

  componentWillUnmount = () => this.clearTimer(); // remove timeout in case of component unmount

  clearTimer = () => clearTimeout(this.timeout); // clear timeout

  timer = () => this.setState({ showChild: false }, () => this.clearTimer()); // update state and clear timeout

  setTimer = () => (this.timeout = setTimeout(this.timer, 5000)); // setup a 5s timeout

  render = () => <div>{this.state.showChild && <Example />}</div>;
}

export default App;

App.test.js

import App from './App';

describe('App', () => {
  it('initially renders a child component', () => {
    expect(wrapper.find('.child')).toHaveLength(1);
  });

  it('removes child component after a 5 second timeout', () => {
    jest.advanceTimersByTime(5000);
    expect(wrapper.find('.child')).toHaveLength(0);
  });
});