为什么redux-mock-store不显示在catch promises中发送的动作?

时间:2016-07-28 16:29:06

标签: redux redux-thunk nock redux-mock-store

在考虑标题问题时我非常糟糕,对不起。

我的问题:

我正在测试我的异步redux操作,例如它的建议in the docs。我使用nock模拟API调用,并使用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 个答案:

答案 0 :(得分:1)

由于您在catch方法中使用嵌套异步函数 - 您需要返回promise:

.catch(error => {
  return error.response.json()
  .then(data => {
    dispatch(setError(data.error))
  })
});

否则,在断言后将调用dispatch。

见原始例子:
https://jsfiddle.net/d5fynntw/ - 没有返回 https://jsfiddle.net/9b1z73xs/ - 返回