监视被拒绝的承诺中调用的函数

时间:2018-03-29 20:45:54

标签: javascript reactjs promise jestjs sinon

我想窥探一个函数来测试当一个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块后才被调用,而且我不知道该怎么做。

2 个答案:

答案 0 :(得分:2)

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

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();
      });
    });
  });
});

答案 1 :(得分:0)

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

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);
    });

});