【问题标题】:Updating state with timer does not return updated values使用计时器更新状态不会返回更新的值
【发布时间】:2019-10-16 05:32:03
【问题描述】:

我是使用 Jest 进行单元测试的新手。该项目有一个进度指示器组件,它使用 setInterval 作为计时器。我需要对“完成”状态变量在“进度”函数中的 20 毫秒滴答声上正确更新进行单元测试。

"react-dom": "^16.8.6",
"react-redux": "^6.0.1",
"react-scripts": "^2.1.3"

progress.js

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import CircularProgress from '@material-ui/core/CircularProgress';

const styles = theme => ({
  progress: {
    margin: theme.spacing.unit * 2
  }
});

class CircularDeterminate extends React.Component {
  state = {
    completed: 0
  };

  componentDidMount() {
    this.timer = setInterval(this.progress, 20);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

  progress = () => {
    let be = this.state.completed;
    console.log('>>>>>> ', this.state.completed);
    const { completed } = this.state;
    this.setState({ completed: completed >= 100 ? 0 : completed + 1 });
    console.log('+++++ ', be, '  ', this.state.completed);
  };

  render() {
    const { classes } = this.props;
    if (!this.props.statusCode) {
      return (
        <div>
          <CircularProgress
            className={classes.progress}
            variant="determinate"
            value={this.state.completed}
          />
        </div>
      );
    } else {
      return null;
    }
  }
}

CircularDeterminate.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(CircularDeterminate);

progressTest.js

import React from 'react';
import { shallow, mount } from 'enzyme';
import Progress from '../progress';

describe('Input Component', () => {
  it('update timer', () => {
    jest.useFakeTimers();
    const wrapper = mount(<Progress />);
    wrapper.instance().setState({ completed: 8 });

    jest.advanceTimersByTime(41);
    wrapper.update();

    expect(wrapper.instance().state.completed).toBe(10);
  });
});

上述测试失败:预期:10,接收:8。我希望“完成”在 2 个滴答声(约 41 毫秒)后为 10。

【问题讨论】:

    标签: javascript reactjs jestjs enzyme create-react-app


    【解决方案1】:

    上述代码中的一个问题(这可能是也可能不是实际问题,具体取决于 Jest 的假计时器的工作方式,但肯定是 a 问题)是您违反了基本规则之一React 状态:由于state updates are asynchronous,如果您要设置新状态基于现有状态,您必须使用setState 的回调形式。所以这是不正确的:

    const { completed } = this.state;
    this.setState({ completed: completed >= 100 ? 0 : completed + 1 });
    console.log('+++++ ', be, '  ', this.state.completed);
    

    这是正确的形式:

    this.setState(
        ({completed}) => ({
            completed: completed >= 100 ? 0 : completed + 1
        }),
        () => {
            console.log('+++++ ', be, '  ', this.state.completed);
        }
    );
    

    【讨论】:

    • 状态更新是异步的,这也是单元测试中的状态没有立即更新的原因吗?
    • @user2251234 - 我不使用 jest,所以我不知道 jest 的假计时器是如何工作的,但测试代码看起来确实是同步的,这是不正确的。我知道我见过异步笑话测试,所以只需要查看这部分是如何完成的。
    猜你喜欢
    • 2019-07-05
    • 1970-01-01
    • 2019-11-09
    • 2022-01-17
    • 2018-09-28
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多