6

具有非常简单的组件:

从 'prop-types' 导入 PropTypes 从 'react' 导入 React 导入 { connect } 从 '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)

我想测试是否在等于doSth时被调用。shouldDoSthtrue

我写了一个测试:

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. 或者,也许我正在做一些根本不应该被允许的事情,并且有“正确”的方式来测试我的案例。我应该只模拟调度并检查它是否使用正确的参数调用?

4

3 回答 3

3

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

如果它是一个道具,那么您可以将它连接到父级(容器)中的 redux。从该组件的 mapDispatchToProps 中删除它。这将使组件更具可测试性。

如果您希望它是连接在此组件中的 redux 操作,那么将操作移出此组件是有意义的,例如actions.js,将其导入此组件中,然后在测试中模拟它jest.mock('actions.js', () => ({doSth: jest.mock()}))

于 2018-06-22T19:37:30.703 回答
2

导出未连接的组件并在测试中使用它,您将能够覆盖 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()
  })
})
于 2020-07-24T08:10:39.160 回答
0

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

在这里,您有两个讨论可能会对您有所帮助:我是否正在测试连接的组件是否正确?并且不能引用包装在 Provider 中或通过连接 Enzyme 的容器

如果你没有正确测试动作或状态,你可能会忘记 mapStateToProps 和 mapDispatchToProps (这些过程已经被 redux 测试过)并通过 props 传递值。

检查以下示例:

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

})

于 2019-12-13T21:10:53.143 回答