如何使用 Jest 和 Enzyme 测试随时间更新的 React 组件?

How to test a React component that update over time with Jest and Enzyme?

我有这个 React 组件

export class Timer extends Component {

constructor(props) {
    super(props);
    this.state = {i : props.i};
}

componentDidMount(){
    this.decrementCounter();
}

decrementCounter(){
    if(this.state.i < 1){
        return;
    }
    setTimeout(() => {
        this.setState({i : this.state.i - 1})
        this.decrementCounter()}, 1000);
}

render(){
    return <span>{this.state.i}</span>
}}

而我想表达这样一个测试

jest.useFakeTimers();
it('should decrement timer ', () => {
    const wrapper = shallow(<Timer i={10} />);
    expect(wrapper.text()).toBe("10");
    jest.runOnlyPendingTimers();
    expect(wrapper.text()).toBe("9");
});

目前第一个期望通过但第二个失败

Expected value to be (using ===):
      "9"
    Received:
      "10"

如何正确测试此组件?

使用Full Rendering API, mount(...)

Full DOM rendering is ideal for use cases where you have components that may interact with DOM APIs, or may require the full lifecycle in order to fully test the component (i.e., componentDidMount etc.)

您可以使用 mount() 而不是像

这样的 shallow()
import React from 'react';
import { mount, /* shallow */ } from 'enzyme';
import Timer from './index';

describe('Timer', () => {
    it('should decrement timer ', () => {
        jest.useFakeTimers();

        const wrapper = mount(<Timer i={10} />);
        expect(wrapper.text()).toBe("10");
        jest.runOnlyPendingTimers();
        expect(wrapper.text()).toBe("9");

        jest.useRealTimers();
    });
});

或者您可以将其他对象传递给 shallow 以将其检测到 运行 生命周期方法

options.disableLifecycleMethods: (Boolean [optional]): If set to true, componentDidMount is not called on the component, and componentDidUpdate is not called after setProps and setContext.

const options = {
  lifecycleExperimental: true,
  disableLifecycleMethods: false 
};

const wrapper = shallow(<Timer i={10} />, options);

我测试过了。有效。

hinok:~/workspace $ npm test

> c9@0.0.0 test /home/ubuntu/workspace
> jest

 PASS  ./index.spec.js (7.302s)
  Timer
    ✓ should decrement timer  (28ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.162s
Ran all test suites.