Стратегия тестирования на Relay + React

Сейчас я экспериментирую с React + Relay + Graphql. К сожалению, я не могу найти простого и удобного способа протестировать компонент React, заключенный в Relay Container.

В принципе, я хотел бы достичь этих целей с помощью TDD,

  1. Визуализируйте контейнер и протестируйте его содержимое,
  2. Измените переменные и проверьте его изменения на содержании.

По сравнению с React + Flux, React + Relay больше похож на черный ящик или декларативен.

Я вижу, как люди издеваются над Relay.createContainer, чтобы обойти Relay и просто тестируют компонент React. Он оставляет часть реле открытой, и невозможно управлять этой частью путем тестирования. https://github.com/facebook/relay/issues/161

Кроме того, я прочитал тестовые примеры Relay, и это действительно утомительно, чтобы визуализировать фиктивный контейнер. https://github.com/facebook/relay/blob/master/src/ tools / mocks /RelayTestUtils.js

Буду очень признателен, если поделитесь своим решением.

Спасибо!


person user2741411    schedule 24.09.2015    source источник
comment
Думаю, это лучшая идея: stackoverflow.com/questions/38327428/   -  person Sibelius Seraphini    schedule 10.11.2016


Ответы (2)


Я пытался тестировать контейнеры Relay, как компоненты в приложении Flux. В частности, я хочу убедиться, что они отображают правильный контент для данного состояния и свойств и что они вызывают методы для изменения данных в соответствующих местах; в Flux это призыв к создателю действия, в Relay - это призыв к Relay.Store.update или this.props.relay.setVariables.

Моей первой попыткой было построить RelayTestUtil объект с помощью renderContainerIntoDocument метода. Я во многом основывал его на https://github.com/facebook/relay/blob /master/src/tools/< sizesmocks, https://github.com/facebook/relay/blob/master/src/legacy/store/ и Relay Контейнерные тесты. При этом использовалось минимальное количество имитаций, и он отлично подходил для тестирования рендеринга контейнера, но был совершенно бесполезен для тестирования изменений данных. Попытки слежки за звонками в Relay.Store.update и this.props.relay.setVariables или имитировать изменения данных стали еще больше проблем, чем это того стоило.

Я решил добавить __mocks__\react-relay.js, чтобы полностью имитировать Relay, и использовал более простую версию RelayTestUtils.renderContainerIntoDocument для вставки свойств Relay в контейнер. Я не совсем доволен этим решением, но, похоже, пока оно работает.

__mocks__\react-relay.js:

var Relay = require.requireActual('react-relay');
var React = require('react');

module.exports = {
  QL: Relay.QL,
  Mutation: Relay.Mutation,
  Route: Relay.Route,
  Store: {
    update: jest.genMockFn()
  },
  createContainer: (component, containerSpec) => {
    const fragments = containerSpec.fragments || {};

    // mock the static container methods
    Object.assign(component, { getFragment: (fragmentName) => fragments[fragmentName] });

    return component;
  }
};

RelayTestUtils.js:

const React = require('react');
const ReactDOM = require('react-dom');


const RelayTestUtils = {
  renderContainerIntoDocument(containerElement, relayOptions) {
    relayOptions = relayOptions || {};

    const relaySpec = {
      forceFetch: jest.genMockFn(),
      getPendingTransactions: jest.genMockFn().mockImplementation(() => relayOptions.pendingTransactions),
      hasOptimisticUpdate: jest.genMockFn().mockImplementation(() => relayOptions.hasOptimisticUpdate),
      route: relayOptions.route || { name: 'MockRoute', path: '/mock' },
      setVariables: jest.genMockFn(),
      variables: relayOptions.variables || {}
    };

    return ReactDOM.render(
      React.cloneElement(containerElement, { relay: relaySpec }),
      document.createElement('div')
    );
  }
};

export default RelayTestUtils;

Тесты выглядят примерно так, где fragmentData соответствует форме ответа GraphQL:

it('changes items', () => {
  const myContainer = RelayTestUtils.renderContainerIntoDocument(
    <MyContainer { ...fragmentData }/>, 
    { variables: { itemId: 'asdf' } }
  );
  myContainer.changeItem();
  expect(myContainer.props.relay.setVariables).toBeCalled();
});
person agrauch    schedule 02.10.2015
comment
Разве нельзя было бы просто «имитировать» сетевой уровень? Так же, как и pretender (github.com/pretenderjs/pretender), ретранслятор действительно мог отправить запрос, но затем вместо того, чтобы разговаривать с сервером, он просто возвращает фиктивные данные. - person Markus; 15.11.2015
comment
@agrauch, не могли бы вы предоставить репо с примером? - person Sibelius Seraphini; 14.10.2016

Я написал в блоге сообщение о том, как протестировать Relay с помощью Jest на работающем сервере GraphQL: https://medium.com/entria/relay-integration-test-with-jest-71236fb36d44#.an74bdopy

Это репо https://github.com/sibelius/relay-integration-test содержит примеры тестирования React Web и React Native с использованием Relay

person Sibelius Seraphini    schedule 07.12.2016