如何模拟和测试 redux-thunk 动作?

How to mock and test redux-thunk actions?

我找不到一种方法来正确测试在其主体内使用 其他 操作的异步 redux 操作:

import {postRequest} from './http'

export function saveAnswer (id, answer) {
  return (dispatch) => {
    dispatch({type: SAVE_ANSWER})

    return dispatch(postRequest(ANSWERS_ENDPOINT, {id, answer}))
  }
}

我想存根 postRequest 这样它的逻辑就不会被执行。

我已经设置了规格:

import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import * as ACTIONS from '../answers'
import * as HTTP_ACTIONS from '../http'

const mockStore = configureMockStore([thunk])
const store = mockStore({})


describe('saveAnswer()', () => {
  it('test', () => {
    sinon.stub(HTTP_ACTIONS, 'postRequest').returns(Promise.resolve({}))

    store.dispatch(ACTIONS.saveAnswer(ID, ANSWER))
  })
})

当我 运行 规范时,我得到这个错误: Error: Actions must be plain objects. Use custom middleware for async actions.

我不明白我做错了什么,但它必须做一些存根 postRequest 操作。

我怎样才能正确地存根那个动作?

如果您使用 redux-thunkdispatch 的参数必须是函数或普通对象。在您的情况下 postRequest returns Promise 对象不是普通对象(也不是函数;)。结果,您使用 promise 对象作为参数调用 dispatch。因此,请确保您调用 dispatch 时使用的参数是函数或普通操作对象(使用 type 属性)。

您可以像这样重写您的代码(假设 postRequest return 的承诺)然后错误应该消失:

import {postRequest} from './http'

export function saveAnswer (id, answer) {
  return (dispatch) => {
    dispatch({type: SAVE_ANSWER})
    postRequest(ANSWERS_ENDPOINT, {id, answer})
      .then((response) => dispatch({
         type: ANSWER_SAVED,
         data: response
      }));
  };
}

评论后回复更新:

因此,由于 postRequest 不是 return Promise 对象而是函数,问题在于你如何存根它。请试试这个(存根也应该 return 函数而不是 Promise 对象):

const mockFuntion = () => Promise.resolve({}); // here can also  be an spy function if needed
sinon.stub(HTTP_ACTIONS, 'postRequest').returns(mockFuntion);