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

时间:2018-02-09 17:47:46

标签: redux redux-thunk

我找不到如何正确测试在其正文中使用其他操作的异步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行动。

如何正确存根?

1 个答案:

答案 0 :(得分:1)

如果使用redux-thunk dispatch的参数必须是函数或普通对象。在你的情况下postRequest返回Promise对象,它不是普通对象(也不是函数;)。因此,您使用promise对象作为参数调用dispatch。所以请确保使用参数调用dispatch,该参数是函数或普通操作对象(具有type属性)。

您可以像这样重写代码(假设postRequest返回promise),然后错误就会消失:

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没有返回Promise对象,但是函数的问题在于你是如何对它进行存根的。请尝试这个(存根也应该返回函数而不是Promise对象):

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