React / Mobx:集成测试与注入子组件的商店

时间:2019-03-26 17:48:38

标签: reactjs jestjs enzyme mobx react-testing-library

我们正在尝试为所有现有的React组件编写单元/集成测试。我们目前正在将React与Mobx 4结合使用,而测试大多使用react-testing-library / jest编写。我们也确实在某些区域使用了酶来利用浅层渲染。 我们的问题是,当我们进入某些“页面”或容器组件时,会遇到诸如“ MobX进样器:存储'teamStore'不可用!请确保它由某些提供程序提供”之类的错误。

我们做了一些挖掘工作,但在搜索相似问题以供参考时找不到任何东西。我们确实知道这是由直接将存储注入到子组件中并被调用到我们的容器/页面中的子组件引起的。

我的问题是:测试框架内是否有任何方法可以将在容器组件中创建的模拟存储传递给子组件?显然,如果我们将商店作为道具从父级传递给子级,就可以解决此问题,但是我们试图避免以任何方式修改组件本身。

如果上述操作不可行,我们是否还有其他选择,而无需重构组件以根据需要传递向下存储,而不是直接注入子组件中?


    import React, { Component } from "react";
    import { inject, observer } from "mobx-react";
    import { Container, Grid, Segment } from "semantic-ui-react";
    import ChildComp from "../../components/ChildComp";

    @inject("userStore")
    @observer
    class ParentComponent extends Component {

      render() {
        return (
            <Container className="parent">
                <Segment basic>
                    <h1>Hello</h1>
                    <ChildComp />
                </Segment>
            </Container>
        );
      }
    }

    export default ParentComponent;


    import React, { Component } from "react";
    import { inject, observer } from "mobx-react";
    import { Container, Grid, Segment } from "semantic-ui-react";

    @inject("teamStore")
    @observer
    class ChildComp extends Component {

      render() {
        return (
            <Segment basic>
                <p>How can I help you?</p>
            </Segment>
        );
      }
    }

    export default ChildComp;

1 个答案:

答案 0 :(得分:2)

通过开玩笑,您可以模拟mobx的各个部分以提供自己的模拟存储,因此,代替运行真实的注入功能,您可以提供自己的注入功能。

使用该自定义注入功能,您可以返回假商店(需要与原始商店匹配相同的接口)。

如果要通过导入创建的模拟来用值来预填充商店(jest不允许在使用jest.mock时使用模块/全局范围内的变量)

这是实现此目的的示例代码(这是未经测试的代码,就在这里写在stackoverflow上,因此可能需要一些调整才能正确使用)。

jest.mock('mobx-react', () => {
  // get the original reference to mobx-react
  const originalMobx = require.requireActual('mobx-react');

  // create your fake stores, they should have the same interface as the real store
  const mockStores = {
    userStore: new UserStore()
  };

  return {
    ...originalMobx, // allow to import the original properties in react-mobx
    // override the inject decorator to instead return the fake store as a prop    
    inject: (injectName) => (component) => (props) => {
      // render the real component with the additional prop
      return react.createElement(component, {...props, [injectName]: mockStores[injectName] })  
    },
    mockStores // Allows access afterwards via import e.g import { mockStores } from 'mobx-react'
  }
});

一旦模拟了mobx-react注入函数,就可以通过以下方式引用商店以预先填充值:

import { mockStores } from 'mobx-react';

test('my test', () => {
  mockStores.userStore.clearUsers();

  // render the component here
})

还有另一种解决方案,您可以用Provider的{​​{1}}包装经过测试的组件,并提供假商店。

因此测试将预先初始化它们并传递上下文。

例如

mobx-react