4

我们正在尝试为所有现有的 React 组件编写单元/集成测试。我们目前正在将 React 与 Mobx 4 一起使用,测试主要使用 react-testing-library/jest 编写。我们确实在某些区域使用了 Enzyme 以利用浅层渲染。我们的问题是,当我们访问一些“页面”或容器组件时,我们会遇到错误,例如“MobX 注入器:存储 'teamStore' 不可用!确保它是由某个 Provider 提供的”

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

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

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


    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;

4

1 回答 1

4

使用 jest 你可以模拟 mobx 的一部分来提供你自己的模拟存储,所以你可以提供你自己的注入函数而不是运行真正的注入函数。

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

如果您想通过导入您创建的模拟来使用值预先填充存储(在使用 jest.mock 时,jest 不允许使用模块/全局范围上的变量)

这是实现此目的的示例代码(这是在 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 注入函数,你可以引用 store 来预填充值:

import { mockStores } from 'mobx-react';

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

  // render the component here
})

还有一个替代解决方案,您可以只使用Providerfrom包装测试组件mobx-react并提供假商店。

所以测试会预先初始化它们并传递上下文。

例如

test('my comp', () => {
 const userStore = new UserStore();
 const component = shallow(
   <Provider userStore={userStore}>
     <MyComponent />
   </Provider>
 )
});
于 2019-04-29T16:24:42.917 回答