为什么redux模拟商店没有';不显示在捕获承诺中发送的操作?

为什么redux模拟商店没有';不显示在捕获承诺中发送的操作?,redux,redux-thunk,nock,redux-mock-store,Redux,Redux Thunk,Nock,Redux Mock Store,当涉及到标题问题时,我很糟糕,对此我很抱歉 我的问题是: 我正在按照建议对我的异步redux操作进行单元测试。我使用nock模拟API调用,并使用redux模拟存储检查调度的操作。到目前为止,它工作得很好,但我有一个测试失败了,尽管它显然确实有效。已调度的操作既不会显示在由store.getActions()返回的数组中,也不会在store.getState()中更改状态。我确信它确实会发生,因为我可以在手动测试时看到它,并使用Redux开发工具观察它 在这个动作分派中唯一不同的是,它在一个承诺

当涉及到标题问题时,我很糟糕,对此我很抱歉

我的问题是: 我正在按照建议对我的异步redux操作进行单元测试。我使用
nock
模拟API调用,并使用
redux模拟存储
检查调度的操作。到目前为止,它工作得很好,但我有一个测试失败了,尽管它显然确实有效。已调度的操作既不会显示在由
store.getActions()
返回的数组中,也不会在
store.getState()
中更改状态。我确信它确实会发生,因为我可以在手动测试时看到它,并使用Redux开发工具观察它

在这个动作分派中唯一不同的是,它在一个承诺中被调用,而在另一个承诺中被捕获。(我知道这听起来很混乱,看看代码就知道了!)

我的代码是什么样子的: 动作:

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))
            })
        });
    };
}
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'
            })
        })
});
这个
httpPost
方法只是
fetch
的包装器,如果状态代码不在200-299范围内,它就会抛出,如果没有失败,它已经将json解析为一个对象。我可以在这里添加它,如果它看起来相关的话,但我不想让它比现在更长

没有显示的操作是
dispatch(setError(data.error))

测试:

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))
            })
        });
    };
}
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;
};
export const httpPost=(url,数据)=>(
获取(url{
方法:“POST”,
headers:createHeaders(),
正文:JSON.stringify(数据),
})
.然后(检查状态)
.then(response=>response.json())
);
const checkStatus=(响应)=>{
如果(response.status>=200&&response.status<300){
返回响应;
}
常量错误=新错误(response.statusText);
error.response=响应;
投掷误差;
};

因为您在catch方法中使用嵌套异步函数-您需要返回承诺:

.catch(error => {
  return error.response.json()
  .then(data => {
    dispatch(setError(data.error))
  })
});
否则,将在断言后调用dispatch

参见基本示例:
-不返回

-返回后

如果有一个
redux mock store
标签就好了。它应该在路上:)请添加一个setError@fahrradflucht如果答案正确,请标记为正确。