如何模拟道具,实际上是连接Redux的动作创建者?

时间:2017-07-11 09:49:09

标签: reactjs testing redux sinon enzyme

在集成测试中,我想测试一个连接的动作创建者是否被调用。

describe('SomeContainer', () => {
  let subject, store, fancyActionCreator

  beforeEach(() => {
    store = createStore(combineReducers({ /* ... */ }))
    fancyActionCreator = sinon.spy()
    const props = {
      fancyActionCreator
    }
    subject = (
      <Provider store={store}>
        <SomeContainer {...props} />
      </Provider>
    )
  })

  it('calls fancyActionCreator on mount', () => {
    mount(subject)
    expect(fancyActionCreator.callCount).to.equal(1)
  })
}

componentWillMount内调用动作创建者,并在测试环境之外按预期工作。

问题是原始的动作创建者在测试中被调用,并且没有被正确地嘲笑。

我感觉这是因为Redux的connect()方法正在取代间谍:

connect(mapStateToProps, { fancyActionCreator })(SomeContainer)

1 个答案:

答案 0 :(得分:2)

您使用商店安装了组件。如果你从mount调用中获取返回值,它会为你提供反应元素的酶包装。此包装器可用于针对存储分派操作:

const enzymeWrapper = mount(subject)
enzymeWrapper.node.store.dispatch({ type: "ACTION", data: "your fake data" });

但这是更多集成类型的测试,因为您正在使用Reducer以及Redux存储状态与您的属性的连接。

这是我唯一可以测试Redux存储状态到组件属性的连接的测试。如果你以别的方式伪造属性,你可能会覆盖你的组件逻辑,但你缺少将属性连接到存储的部分。

我建议将您的组件分为表示组件和容器组件。演示文稿不需要使用商店,因此您可以通过传递不同的属性来锤击其逻辑。容器组件关注的是将存储连接到表示组件。因此,对于容器组件,您将使用我所描述的测试类型。

评论的反应:

实际上,mount vs shallow对表示/未连接组件的使用并不是那么直接。有时您在演示组件上使用需要由mount渲染的子组件(例如,由于某种原因,react-select需要DOM)。

但通常是的,除非您意识到需要shallow,否则应该努力将mount用于表示组件。