【问题标题】:How to test a component function being called when componentDidMount?如何测试componentDidMount时调用的组件函数?
【发布时间】:2020-11-26 13:44:23
【问题描述】:

我有一个 React JS 组件 MyComponent,我想测试以下用例:

组件挂载时应该调用updateSomething()

我想出了以下代码:

被测系统 (SUT)

export class MyComponent extends React.Component<Props, State> {
    public componentDidMount() {
        console.log("componentDidMount"); // Debug purpose.
        this.fetchSomething()
            .then(() => {
                console.log("fetchSomething"); // Debug purpose.
                this.updateSomething();
            });
    }

    // These are public for simplicity
    public async fetchSomething(): Promise<any> { }
    public updateSomething() {
         console.log("updateSomething"); // Debug purpose.
    }
}

测试

it("should update something, when on mount", () => {
    const props = { ...baseProps };
    sinon.stub(MyComponent.prototype, "fetchSomething").resolves();
    const spy = sinon.spy(MyComponent.prototype, "updateSomething");

    shallow(<MyComponent {...props} />);

    sinon.assert.calledOnce(spy);
});

结果是测试失败并显示AssertError: expected updateSomething to be called once but was called 0 times,但所有三个console.log() 都打印了。

我的理解是因为我想在挂载时测试事件,所以我必须在它创建之前对其进行监视/存根,因此我必须监视MyComponent.Prototype。另外,对于fetchSomething(),我必须存根异步调用并使其成为.resolves() 以让它继续。

但我不明白它怎么还能console.log("updateSomething") 不被监视。

【问题讨论】:

    标签: javascript reactjs testing enzyme sinon


    【解决方案1】:

    我不知道sinon,也不知道ts,但简单的jsjest 会是这样的:

    fetchSomething() = Promise.resolve();

    然后,在您的测试中,您不必模拟它,只需使用:

    const spy = jest.spyOn(MyComponent.prototype, 'updateSomething');

    查看是否被调用:

    expect(spy).toHaveBeenCalled();

    【讨论】:

    • 谢谢你的回答,这个方法和OP的结果是一样的。简单地做MyComponent.prototype.prepareWithImageSize = () =&gt; Promise.resolve(); 对我不起作用。我最终得到了错误消息expect(jest.fn()).toHaveBeenCalled(); Expected number of calls: &gt;= 1; Received number of calls: 0。但我可以看到updateSomething() 里面的日志。您对在异步情况下如何发生这种情况有任何想法吗?
    • 好吧,这很奇怪......但你可以尝试将你的浅层渲染分配给一个变量,然后像这样监视:const spy = jest.spyOn(wrapper.instance(), 'updateSomething')。不过,我不知道为什么以前的解决方案不适合你:(
    • np,仍然感谢您的努力。我会再调查一下
    【解决方案2】:

    根据来自this post 的 cmets/answer,断言在 .updateSomething 被调用之前出现。要解决这个问题,我必须等待componentDidMount 生命周期方法。

    所以固定的程序如下:

    // SUT
    
    public async componentDidMount() {
        //...
        return this.fetchSomething()
            .then(() => {
                //...
            });
    }
    
    // Test
    
    it("should update something, when on mount", () => {
        const props = { ...baseProps };
    
        // Disable lifecycle here to enable stub in between.
        const wrapper = shallow(<MyComponent {...props} />, { disableLifecycleMethods: true });
    
        sinon.stub(wrapper.instance(), "fetchSomething").resolves();
        const stub = sinon.stub(wrapper.instance(), "updateSomething");
    
        // Actually call component did mount.
        wrapper.instance().componentDidMount().then(() => {
             sinon.assert.calledOnce(stub);
        });
    });
    

    【讨论】:

      猜你喜欢
      • 2017-05-22
      • 1970-01-01
      • 2017-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 2018-07-21
      • 1970-01-01
      相关资源
      最近更新 更多