将jest.fn()函数传递到酶浅渲染中的mapDispatchToProps

时间:2018-06-22 14:11:55

标签: javascript redux jestjs enzyme redux-mock-store

具有非常简单的组件:

从'prop-types'导入PropTypes 从'react'导入React 从'react-redux'导入{connect}

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)

我想测试当doSth等于shouldDoSth时是否调用true

我写了一个测试:

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()
  })
})

但似乎尽管我将doSth作为道具传递,但在执行mapDispatchToProps时它却被console.log('im not a mock')覆盖。

如何正确传递/覆盖/分配doSth函数以使组件使用模拟而不是mapDispatchToProps中的函数。也许我正在做一些根本不应该做的事情,并且有“适当”的方式测试我的案子。我应该只是模拟调度,并检查它是否带有正确的参数?

3 个答案:

答案 0 :(得分:1)

我认为您需要弄清的一件事是,您是否想doSth成为道具,还是要在mapDispatchToProps中连接的redux动作。

如果它是道具,则​​可以将其连接到父对象(容器)中的redux。从此组件的mapDispatchToProps中删除它。这样可以使组件更易于测试。

如果您希望它是连接到该组件中的一个Redux动作,则将该动作从该组件中移出actions.js之类的位置,然后将其导入该组件中,然后对其进行模拟测试jest.mock('actions.js', () => ({doSth: jest.mock()}))

答案 1 :(得分:1)

导出未连接的组件并在测试中使用它,您将可以覆盖mapDispatchToProps操作。

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()
  })
})

答案 2 :(得分:0)

我认为您应该问自己是否要测试未连接的MyComponent或已连接的MyComponent。

这里有两个讨论可以帮助您:Am I testing connected components correclty?Can't reference containers wrapped in a Provider or by connect with Enzyme

如果您未测试动作或状态未正确说明,则可能会忘记mapStateToProps和mapDispatchToProps(那些进程已由redux测试),并通过prop传递值。

检查以下示例:

describe('MyComponent', () => {

let wrapper;

const doSthMock = jest.fn();

beforeEach(() => {

    const componentProps = {
        doSth: true,
    };

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

});

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

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

})