React / Mobx: интеграционные тесты с хранилищами, внедренными в дочерние компоненты - PullRequest
3 голосов
/ 26 марта 2019

Мы пытаемся написать модульные / интеграционные тесты для всех наших существующих компонентов React.В настоящее время мы используем React с Mobx 4, при этом тесты пишутся в основном с использованием response-testing-library / jest.Мы также использовали Enzyme в некоторых областях, чтобы использовать поверхностный рендеринг.Наша проблема в том, что, когда мы добираемся до некоторых наших «страниц» или компонентов контейнера, мы получаем ошибки, такие как «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 Ответ

2 голосов
/ 29 апреля 2019

Используя jest, вы можете смоделировать части mobx для создания собственного хранилища, поэтому вместо запуска реальной функции инъекции вы можете вместо этого предоставить собственную функцию инъекции.

Используя эту пользовательскую функцию инъекции, вы можете вернуть подделкуstore (который должен совпадать с тем же интерфейсом, что и исходное хранилище).

Если вы хотите предварительно заполнить хранилище значениями, импортировав созданный макет (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-реагировать, вы можете обратиться к хранилищу, чтобы предварительно заполнить значения:

import { mockStores } from 'mobx-react';

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

  // render the component here
})

Существует также альтернативное решение, где вы можете просто обернуть тестируемый компонент с помощью Providerот mobx-react и поставка поддельных магазинов.

, поэтому тест предварительно их инициализирует и передает контекст.

Например,

test('my comp', () => {
 const userStore = new UserStore();
 const component = shallow(
   <Provider userStore={userStore}>
     <MyComponent />
   </Provider>
 )
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...