Search code examples
reduxjestjsenzymesinon

Redux testing: Actions must be plain objects. Use custom middleware for async actions


I have a Redux app and it is working perfectly without any errors. Now I am trying to test it with Enzyme, Jest and Sinon:

  it('calls constructor', () => {
    sinon.spy(SavedVariantsComponent.prototype, 'constructor')
    const store = configureStore()(STATE1)
    wrapper = mount(<SavedVariantsComponent store={store} match={{ params: {} }} />)
    expect(SavedVariantsComponent.prototype.constructor).toHaveProperty('callCount', 1)
  })

In SavedVariantsComponent I have mapDispatchToProps:

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onSubmit: (updates) => {
      dispatch(updateSavedVariantTable(updates))
      const { match, analysisGroup } = ownProps
      const { familyGuid, variantGuid, tagArray, gene } = match.params
      const familyGuids = familyGuid ? [familyGuid] : (analysisGroup || {}).familyGuids
      const combineVariants = /combined_variants/.test(match.url)
      dispatch(loadSavedVariants(combineVariants, familyGuids, variantGuid, tagArray, gene))
    },  
    loadSavedVariants: (...args) => dispatch(loadSavedVariants(...args)),
  }
}

And loadSavedVariants look like that:

export const loadSavedVariants = (combineVariants, familyGuids, variantGuid, tagArray, gene = '') => {
  return (dispatch, getState) => {
...
...

and the error while running jest is:

Actions must be plain objects. Use custom middleware for async actions.

Which makes an HTTP Request that may not work in the current case. How to fix this error? I need to test that the constructor was called, but later on will also need to see how the inner Components are rendered, so need to have mount there. I suppose I am doing something wrong in testing and not in the real code since the latter is working without any errors, warnings or issues.


Solution

  • You probably need to configure your mock store to work with redux-thunk. See: https://github.com/dmitry-zaets/redux-mock-store#asynchronous-actions

    import configureStore from 'redux-mock-store'
    import thunk from 'redux-thunk'
    
    const middlewares = [thunk] // add your middlewares like `redux-thunk`
    const mockStore = configureStore(middlewares)