Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass jest.fn() function to mapDispatchToProps in enzyme shallow render

Having very simple component:

import PropTypes from 'prop-types' import React from 'react' import { connect } from 'react-redux'

class MyComponent extends React.Component {
  componentWillMount() {
    if (this.props.shouldDoSth) {
      this.props.doSth()
    }
  }

  render () {
    return null
  }
}

MyComponent.propTypes = {
  doSth: PropTypes.func.isRequired,
  shouldDoSth: PropTypes.bool.isRequired
}

const mapStateToProps = (state) => {
  return {
    shouldDoSth: state.shouldDoSth,
  }
}

const mapDispatchToProps = (dispatch) => ({
  doSth: () => console.log('you should not see me')
})

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)

I want to test if doSth is called when shouldDoSth is equal true.

I've written a test:

describe('call doSth when shouldDoSth', () => {
  it('calls doSth', () => {
    const doSthMock = jest.fn()
    const store = mockStore({shouldDoSth: true})
    shallow(<MyComponent doSth={doSthMock}/>, { context: { store } }).dive()
    expect(doSthMock).toHaveBeenCalled()
  })
})

but it seems that although I pass doSth as props it gets overridden by mapDispatchToProps as console.log('im not a mock') is executed.

How to properly pass/override/assign doSth function to make component use mock instead of function from mapDispatchToProps. Or maybe I'm doing something which should not be allowed at all and there is 'proper' way of testing my case. Shall I just mock dispatch instead and check if it is called with proper arguments?

like image 524
Filip Bartuzi Avatar asked Jun 22 '18 14:06

Filip Bartuzi


People also ask

How do I cover mapDispatchToProps in jest?

it('mapDispatchToProps works as expected', () => { const actionProps = mapDispatchToProps({ submitClaimsForm: jest. fn() }); actionProps. submitClaimsForm(); expect(submitClaimsForm). toHaveBeenCalled(); });

What is the difference between mapStateToProps () and mapDispatchToProps ()?

The mapStateToProps() method is used to render the stored data to the component. The mapDispatchToProps() method is used to render the action creators with props to the component. The entirety of the results of the mapStateToProps() method is a plain object which is later merged into the component's prop.

How do I test mapStateToProps using jest?

Steps: extract each mapDispatchToProps property as a separate action creator function in another file. extract each mapStateToProps property as a separate selector function in another file. write tests for the selectors and action creators.


2 Answers

I think one thing you need to figure out is whether you want doSth to be a prop, or a redux action connected in mapDispatchToProps.

If it's a prop, then you would connect it to redux in a parent (container). Remove it from this component's mapDispatchToProps. This would make the component more testable.

If you want it to be a redux action connected in this component, then it would make sense to move the action out of this component, somewhere like actions.js, import it in this component, and then mock it in the test jest.mock('actions.js', () => ({doSth: jest.mock()}))

like image 106
Herman Starikov Avatar answered Oct 24 '22 17:10

Herman Starikov


Export the unconnected component and use it in the test and you will be able to override the mapDispatchToProps action.

export class MyComponent extends React.Component {
  componentWillMount() {
    if (this.props.shouldDoSth) {
      this.props.doSth()
    }
  }

  render () {
    return null
  }
}

MyComponent.propTypes = {
  doSth: PropTypes.func.isRequired,
  shouldDoSth: PropTypes.bool.isRequired
}

const mapStateToProps = (state) => {
  return {
    shouldDoSth: state.shouldDoSth,
  }
}

const mapDispatchToProps = (dispatch) => ({
  doSth: () => console.log('you should not see me')
})

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)




import {MyComponent} from '../MyComponent'
describe('call doSth when shouldDoSth', () => {
  it('calls doSth', () => {
    const doSthMock = jest.fn()
    const store = mockStore({shouldDoSth: true})
    shallow(<MyComponent doSth={doSthMock}/>, { context: { store } }).dive()
    expect(doSthMock).toHaveBeenCalled()
  })
})
like image 39
Prakash Avatar answered Oct 24 '22 18:10

Prakash