【问题标题】:spying a function called in a rejected promise监视在被拒绝的承诺中调用的函数
【发布时间】:2018-09-08 22:10:38
【问题描述】:

我想监视一个函数来测试当一个 promise 被拒绝时这个函数是否在一个 catch 块中被调用。我的代码是这样的反应组件

export class ResetPassword extends Component {
    handleSubmit = e => {
        e.preventDefault();

        this.props
            .resetPassword()
            .then(() => {
                this.props.history.push(LOGIN_PATH);
            })
            .catch(({ error }) => {
                this.props.displayErrorAlert('impossible to change password. You should ask for a new reset password link',6000);
            });
    };
}

这里我想测试一下函数displayErrorAlert是否被调用了。我做了这个测试

it('validate form', () => {
    const resetPassword = () => {
        return Promise.reject({
            error: {
                response: {
                    data: {
                        errors: [
                            {
                                title: 'foo',
                            },
                        ],
                    },
                },
            },
        });
    };

    const displaySpy = sinon.spy();

    const wrapper = mount(
        <ResetPassword
            history={{}}
            resetPassword={resetPassword}
            displayErrorAlert={displaySpy}
        />
    );

    wrapper.instance().handleSubmit({
        preventDefault: () => {},
    });

    expect(displaySpy.calledOnce).toEqual(true);
});

间谍被调用,但当然是异步的,所以我的测试总是失败。我想找到一种方法来测试函数是否仅在调用 catch 块后才被调用,但我不知道该怎么做。

【问题讨论】:

    标签: javascript reactjs promise jestjs sinon


    【解决方案1】:

    Sinon 为您提供处理 Promise 时所需的一切,您可以使用 sinon.stub() 解决和拒绝存根的 Promise。

    const resetPassword = sinon.stub();
    const displayErrorAlert = sinon.spy();
    const preventDefault = sinon.spy();
    
    const props = {
      resetPassword,
      displayErrorAlert,
      history: []
    };
    
    describe('Given a component', () => {
      let component;
    
      describe('when rendered', () => {
        beforeAll(() => {
          component = shallow(<ResetPassword {...props} />);
        });
    
        describe('and the form is submitted and there is an error reseting the password', () => {
          beforeAll(() => {
            resetPassword.rejects(new Error('Oops!'));
            component.find('button').simulate('click', { preventDefault });
          });
    
          it('should invoke the displayErrorAlert function', () => {
            expect(displayErrorAlert.calledOnce).toBeTruthy();
          });
        });
      });
    });
    

    【讨论】:

    • 我必须挂载它,因为按钮在子组件中。
    • 好的,很公平。监视displayErrorAlert 应该还是一样的。
    • 好的,所以我使用了mount 函数并在表单上模拟了我的事件,是的,它可以工作:-) 感谢您的解决方案。我在您发布答案的同时找到了另一个,我也会添加我的。
    • 嗯,不,随着您所做的更改,它不再起作用了。
    【解决方案2】:

    我找到了另一种解决方案,我在 handleSubmit 函数中返回了承诺并在我的测试中使用它。

    export class ResetPassword extends Component {
        handleSubmit = e => {
            e.preventDefault();
    
            return this.props
                .resetPassword()
                .then(() => {
                    this.props.history.push(LOGIN_PATH);
                })
                .catch(({ error }) => {
                    this.props.displayErrorAlert('impossible to change password. You should ask for a new reset password link',6000);
                });
        };
    }
    

    和我的测试

    it('validate form', () => {
        const resetPassword = () => {
            return Promise.reject({
                error: {
                    response: {
                        data: {
                            errors: [
                                {
                                    title: 'foo',
                                },
                            ],
                        },
                    },
                },
            });
        };
    
        const displaySpy = sinon.spy();
    
        const wrapper = mount(
            <ResetPassword
                history={{}}
                resetPassword={resetPassword}
                displayErrorAlert={displaySpy}
            />
        );
    
        expect.assertions(1);
        const promise = wrapper.instance().handleSubmit({
            preventDefault: () => {},
        });
    
        return promise.then(() => {
            expect(displaySpy.calledOnce).toEqual(true);
        });
    
    });
    

    【讨论】:

      猜你喜欢
      • 2015-10-26
      • 1970-01-01
      • 2018-05-09
      • 2017-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      相关资源
      最近更新 更多