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

Posted

技术标签:

【中文标题】将 jest.fn() 函数传递给酶浅渲染中的 mapDispatchToProps【英文标题】:Pass jest.fn() function to mapDispatchToProps in enzyme shallow render 【发布时间】:2018-12-02 01:05:35 【问题描述】:

有非常简单的组件:

从“prop-types”导入 PropTypes 从“反应”导入反应 从'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)

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

我写了一个测试:

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 作为道具传递,但在执行 console.log('im not a mock') 时,它会被 mapDispatchToProps 覆盖。

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

【问题讨论】:

【参考方案1】:

我认为你需要弄清楚的一件事是你是否希望 doSth 成为一个道具,或者一个连接在 mapDispatchToProps 中的 redux 操作。

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

如果你希望它是一个连接在这个组件中的redux action,那么将这个action移出这个组件是有意义的,比如actions.js,将它导入到这个组件中,然后在测试中模拟它jest.mock('actions.js', () =&gt; (doSth: jest.mock()))

【讨论】:

【参考方案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()
  )
)

【讨论】:

【参考方案3】:

我认为你应该问问自己是要测试未连接的 MyComponent 还是连接的。

这里有两个讨论可能对您有所帮助:Am I testing connected components correclty? 和 Can't reference containers wrapped in a Provider or by connect with 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();
);

)

【讨论】:

以上是关于将 jest.fn() 函数传递给酶浅渲染中的 mapDispatchToProps的主要内容,如果未能解决你的问题,请参考以下文章

将函数传递给子父级而不重新渲染

如何使用 Promise 将参数传递给 AngularJS 中的函数

如何将 JSON 对象传递给 Flask 中的模板?

Kotlin:如何将一个函数作为参数传递给另一个函数?

如何将数组参数传递给函数

如何将定义的字典传递给 Python 中的 **kwargs?