Я хотел бы шпионить за функцией, чтобы проверить, вызывается ли эта функция в блоке 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 [JS]](https://i.imgur.com/WsjO6zJb.png)


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();
});
});
});
});
Хорошо, достаточно честно. Шпионить за displayErrorAlert все равно должно.
Хорошо, я использовал функцию mount и смоделировал свое событие в форме, и да, оно работает :-) Спасибо за ваше решение. Я нашел еще один, когда вы публикуете свой ответ, я тоже добавлю свой.
Хм, нет, с внесенными вами изменениями это больше не работает.
Я нашел другое решение, возвращаю обещание в функции 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);
});
});
Мне нужно установить его, потому что кнопка находится в дочернем компоненте.