最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Pass jest.fn() function to mapDispatchToProps in enzyme shallow render - Stack Overflow

programmeradmin6浏览0评论

Having very simple ponent:

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

class MyComponent extends React.Component {
  ponentWillMount() {
    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 ponent 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?

Having very simple ponent:

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

class MyComponent extends React.Component {
  ponentWillMount() {
    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 ponent 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?

Share Improve this question edited Nov 12, 2018 at 20:04 skyboyer 23.8k7 gold badges62 silver badges71 bronze badges asked Jun 22, 2018 at 14:11 Filip BartuziFilip Bartuzi 5,9318 gold badges58 silver badges105 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

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 ponent's mapDispatchToProps. This would make the ponent more testable.

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

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

export class MyComponent extends React.Component {
  ponentWillMount() {
    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()
  })
})

I think that you should ask yourself if you want to test the unconnected MyComponent or the connected one.

Here you have two discussions that may help you: Am I testing connected ponents correclty? and Can't reference containers wrapped in a Provider or by connect with Enzyme

If you are not testing the action nor state properly said, you might forget about mapStateToProps and mapDispatchToProps (those processes are already tested by redux) and pass values through props.

Check the following example:

describe('MyComponent', () => {

let wrapper;

const doSthMock = jest.fn();

beforeEach(() => {

    const ponentProps = {
        doSth: true,
    };

    wrapper = mount(
            <MyComponent
                {... ponentProps}
                doSth={doSthMock}
            />
    );

});

it('+++ render the ponent', () => {
    expect(wrapper.length).toEqual(1);
});

it('+++ call doSth when shouldDoSth', () => {
    expect(doSthMock).toHaveBeenCalled();
});

})

发布评论

评论列表(0)

  1. 暂无评论