在 componentDidMount 中测试 setTimeout 的执行?

Test execution of setTimeout inside componentDidMount?

我有以下组件:

class PlayButton extends Component {
    constructor () {
        super();

        this.state = { glow: false };
        this.play = this.play.bind(this);
    }
componentDidUpdate () {
        if (this.props.media.currentTime === 0 && this.props.media.duration !== 0 && !this.state.glow) {
            console.log('entering')
            setTimeout(() => {
                console.log('did time out')
                this.setState({ glow: true });
            }, 3000);
        }

        if (this.props.media.currentTime !== 0 && this.state.glow) {
            this.setState({ glow: false });
        }
    }

我想测试 componentDidMount 中的 setState 但无法完成:

it('button shoould start glowing', () => {
        const wrapper = mount(<PlayButton media={{ currentTime: 0, duration: 1 }}/>);
        wrapper.update()
        jest.runAllTimers();
        expect(wrapper.state('glow')).toBe(true);
    });

有什么想法吗? 谢谢!

您可以传入 setTimeout 的模拟,而不是立即调用回调:

static defaultProps = {
    timeout: setTimeout
}

this.props.timeout(() => {
    console.log('did time out')
    this.setState({ glow: true });
}, 3000);

it('button shoould start glowing', () => {
    const wrapper = mount(<PlayButton media={{ currentTime: 0, duration: 1 }} 
                               timeout={(fn, _) => fn()}}/>);
    wrapper.update()
    jest.runAllTimers();
    expect(wrapper.state('glow')).toBe(true);
});

好吧,我是这样解决的:

it('button shoould start glowing', () => {
        let clock = sinon.useFakeTimers();
        const wrapper = mount(<PlayButton media={{ currentTime: 0, duration: 1 }}/>);
        wrapper.update()
        clock.tick(3000)
        expect(wrapper.state('glow')).toBe(true);
    });

您必须在调用 runAllTimers 后更新包装器。 检查这个 post,它对我来说很好 https://medium.com/@DavideRama/testing-async-setstate-in-react-settimeout-in-componentdidmount-434602abd7db

const items = ['die Straße', 'die Adresse', 'die Nationalität'];

jest.useFakeTimers();

describe('<DelayedList />', () => {
  test('it renders the items with delay', () => {
    const component = shallow(
      <DelayedList items={items} />
    );

    jest.runAllTimers();
    component.update(); // <--- force re-render of the component

    expect(component.state().currentIndex).toEqual(items.length);
    expect(component).toMatchSnapshot();
  });
});