Слежка за функцией, вызванной в отклоненном обещании

Я хотел бы шпионить за функцией, чтобы проверить, вызывается ли эта функция в блоке 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, и я понятия не имею, как это сделать.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
352
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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();
      });
    });
  });
});

Мне нужно установить его, потому что кнопка находится в дочернем компоненте.

manu 30.03.2018 14:21

Хорошо, достаточно честно. Шпионить за displayErrorAlert все равно должно.

dcodesmith 30.03.2018 14:25

Хорошо, я использовал функцию mount и смоделировал свое событие в форме, и да, оно работает :-) Спасибо за ваше решение. Я нашел еще один, когда вы публикуете свой ответ, я тоже добавлю свой.

manu 30.03.2018 14:29

Хм, нет, с внесенными вами изменениями это больше не работает.

manu 30.03.2018 14:45
Ответ принят как подходящий

Я нашел другое решение, возвращаю обещание в функции 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);
    });

});

Другие вопросы по теме