Почему redux-mock-store не показывает действие, отправленное в обещаниях catch?
Мне очень плохо, когда речь заходит о заглавном вопросе, извините за это.
Моя проблема:
Я тестирую свои асинхронные редукционные действия, как это предлагается в документации. Я высмеиваю вызовы API с nock
и проверьте отправленные действия с redux-mock-store
, Пока он отлично работает, но у меня есть один тест, который не проходит, хотя он явно работает. Отправленное действие также не отображается в массиве, возвращаемом store.getActions()
и при этом состояние не изменяется в store.getState()
, Я уверен, что это происходит, потому что я вижу это, когда тестирую вручную и наблюдаю с помощью Redux Dev Tools.
Единственное, что отличается в этой рассылке действий, - это то, что она вызывается в обещании в улове другого обещания. (Я знаю, это звучит странно, просто посмотрите на код!)
Как выглядит мой код:
Действие:
export const login = (email, password) => {
return dispatch => {
dispatch(requestSession());
return httpPost(sessionUrl, {
session: {
email,
password
}
})
.then(data => {
dispatch(setUser(data.user));
dispatch(push('/admin'));
})
.catch(error => {
error.response.json()
.then(data => {
dispatch(setError(data.error))
})
});
};
}
это httpPost
метод это просто обертка fetch
Это выдает, если код состояния не находится в диапазоне 200-299 и уже анализирует JSON для объекта, если он не терпит неудачу. Я могу добавить это здесь, если это кажется уместным, но я не хочу делать это дольше, чем это уже есть.
Действие, которое не появляется, dispatch(setError(data.error))
,
Тест:
it('should create a SET_SESSION_ERROR action', () => {
nock(/example\.com/)
.post(sessionPath, {
session: {
email: fakeUser.email,
password: ''
}
})
.reply(422, {
error: "Invalid email or password"
})
const store = mockStore({
session: {
isFetching: false,
user: null,
error: null
}
});
return store.dispatch(actions.login(
fakeUser.email,
""))
.then(() => {
expect(store.getActions()).toInclude({
type: 'SET_SESSION_ERROR',
error: 'Invalid email or password'
})
})
});
Спасибо, что даже прочитали.
Редактировать:
setError
действие:
const setError = (error) => ({
type: 'SET_SESSION_ERROR',
error,
});
httpPost
метод:
export const httpPost = (url, data) => (
fetch(url, {
method: 'POST',
headers: createHeaders(),
body: JSON.stringify(data),
})
.then(checkStatus)
.then(response => response.json())
);
const checkStatus = (response) => {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
};
1 ответ
Из-за того, что вы используете вложенную асинхронную функцию в методе catch - вам нужно вернуть обещание:
.catch(error => {
return error.response.json()
.then(data => {
dispatch(setError(data.error))
})
});
В противном случае отправка будет вызвана после вашего подтверждения.
Смотрите примитивные примеры:
https://jsfiddle.net/d5fynntw/ - без возврата
https://jsfiddle.net/9b1z73xs/ - с возвращением