在React HOC组件中测试计时器

时间:2018-01-28 17:15:17

标签: reactjs intervals jestjs

我正在尝试测试组件中的间隔,但它不起作用。

组件:

import React, { Component } from "react";

  export const withTimer = WrappedComponent =>enter code here {
    class WithTimer extends Component {
      constructor(props) {
        super(props);
        this.state = {
          elapsedTime: 0
        }
      }

    componentDidMount() {
      this.intervalId = setInterval(
        () =>
          this.setState(({ elapsedTime }) => ({
            elapsedTime: elapsedTime + 1
          })),
        1000
      );
    }

    componentDidUpdate() {
      const { elapsedTime } = this.state;
      if (elapsedTime >= 2) {
        run_function();
      }
    }

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

    render() {
      return (
        <WrappedComponent
          elapsedTime={this.state.elapsedTime}
        />
      );
    }
  }

  return WithTimer;
};

测试:

describe("<WithTimer />", () => {
  const InnerComponent = () => {
    return <div>hello</div>;
  };
  const Comp = withTimer(InnerComponent);

  it("updates correctly", () => {
    const wrapper = shallow(<Comp />, {lifecycleExperimental: true });
    wrapper.update();
    jest.useFakeTimers();
    jest.advanceTimersByTime(3123);
    jest.runAllTimers()
    wrapper.update();

    expect(setInterval).toHaveBeenCalledTimes(1);
  })
});

我尝试了几种组合,但 elapsedTime 没有更新,并且未触发 run_function()。 间隔函数是模拟正确的,但它被称为零次。 我做错了什么?

1 个答案:

答案 0 :(得分:0)

在构造函数中定义属性intervalId,以便在整个类中可以访问。

class WithTimer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            elapsedTime: 0
        }
        this.intervalId = null;
    }
    ...
}

另外,如果定义setInterval以避免组件安装和卸载时出现错误行为,我建议您改进代码检查。

componentDidMount() {
    if(!this.intervalId) {
        this.intervalId = setInterval(
            () =>
                this.setState(({ elapsedTime }) => ({
                    elapsedTime: elapsedTime + 1
            })),
            1000
        );
    }
}

componentWillUnmount() {
    clearInterval(this.intervalId);
    this.intervalId = null;
}