Модульное тестирование - это здорово, тестирование моментальных снимков тоже отлично, но из моей практики лучшие тесты - это те, которые тестируют как бэкэнд, так и фронт (Integration Test). - Григорий Пташко

Так как же выглядит интеграционный тест Relay?

Этот тест заставит контейнеры Relay делать реальные запросы к работающему бэкэнду GraphQL.

Исходный код этого сообщения: https://github.com/sibelius/relay-integration-test (наслаждайтесь как React Web, так и React Native).

Рабочий сервер GraphQL: https://github.com/sibelius/graphql-dataloader-boilerplate

Мотивация

Интеграционные тесты Relay - это самый простой способ убедиться, что вы обнаружите любой сломанный компонент или код, когда вы изменяете свой бэкэнд GraphQL или интерфейсное приложение Relay с помощью React или React Native.

Способ заставить это работать

Эта идея была предложена https://github.com/GrigoryPtashko по этим двум вопросам: facebook / relay # 1281 и facebook / jest # 1898

Я начал копаться в тестировании Jest и понял, что проблема в том, что fetch не полифицируется в среде Jest (facebook / jest # 2071)

Для React Native мне нужно выполнить полифил XMLHttpRequest, чтобы он заработал (sibelius / relay-integration-test)

Для React Web мне нужно выполнить полифил-выборку (sibelius / relay-integration-tes t)

Итоговые тесты выглядят так:

import 'react-native';
import React from 'react';
import Relay from 'react-relay';
import App from '../app';
import RelayStore from '../RelayStore';

// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';

RelayStore.reset(
  new Relay.DefaultNetworkLayer('http://localhost:5000/graphql')
);

const delay = (value) => new Promise(resolve => 
   setTimeout(() => resolve(), value)
);

it('renders correctly', async () => {
  const tree = renderer.create(
    <App />
  );
  // Wait Relay to fetch data
  await delay(3000);

  expect(tree.toJSON()).toMatchSnapshot();
});

Этот тест визуализирует компонент ‹App /›, который является контейнером Relay.Renderer, используя react-test-renderer, затем он будет ждать 3 секунды, чтобы позволить Relay получить необходимые данные, затем мы делаем снимок компонента результата

Шаг за шагом

  1. Добавьте Jest в свой проект
yarn add jest jest-cli react-test-renderer --dev

Для React Web (полифил выборки)

yarn add isomorphic-fetch --dev

Для React Native (предустановка react native jest и полифилл XMLHttpRequest)

yarn add jest-react-native xhr2 --dev

2. Добавьте конфигурацию Jest в свой package.json.

Для React Web

"jest": {
  "setupFiles": [
    "./test/env.js"
  ]
},
"scripts": { 
  "test": "jest"
}

Для React Native

"jest": {
  "preset": "jest-react-native",
  "setupFiles": [
    "./test/env.js"
  ]
},
"scripts": { 
  "test": "jest"
}

3. Создайте файл env.js (настройка тестовой среды).

Для React Web

import 'isomorphic-fetch';

Для React Native

const XMLHttpRequest = require('xhr2');

global.XMLHttpRequest = XMLHttpRequest;

4. Создайте компонент Relay Container для тестирования.

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
} from 'react-native';
import Relay from 'react-relay';
import ViewerQuery from './ViewerQuery';
import { createRenderer } from './RelayUtils';
import RelayStore from './RelayStore';

RelayStore.reset(
  new Relay.DefaultNetworkLayer('http://localhost:5000/graphql')
);

class RelayApp extends Component {
  render() {
    return (
      <View>
        <Text>name: {this.props.viewer.users.edges[0].node.name}</Text>
        <Text>length: {this.props.viewer.users.edges.length}</Text>
      </View>
    );
  }
}

// Create a Relay.Renderer container
export default createRenderer(RelayApp, {
  queries: ViewerQuery,
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        users(first: 2) {
          edges {
            node {
              name
            }
          }
        }
      }
    `,
  },
});

createRenderer - это вспомогательная функция, которая легко создаст для вас Relay.Renderer (проверьте файл здесь: https://gist.github.com/janicduplessis/f513032eb37cdde5d050d9ce8cf0b92a)

Для Интернета я адаптировал версию createRenderer - https://github.com/sibelius/relay-integration-test/blob/master/RelayWeb/src/RelayUtils.js

5. Создайте первый тест интеграции реле.

import 'react-native';
import React from 'react';
import Relay from 'react-relay';
import App from '../app';
import RelayStore from '../RelayStore';
import renderer from 'react-test-renderer';

RelayStore.reset(
  new Relay.DefaultNetworkLayer('http://localhost:5000/graphql')
);

const delay = (value) => new Promise(resolve => 
   setTimeout(() => resolve(), value)
);

it('renders correctly', async () => {
  const tree = renderer.create(
    <App />
  );
  // Wait Relay to fetch data
  await delay(3000);

  expect(tree.toJSON()).toMatchSnapshot();
});

6. Запустите сервер GraphQL.

Я использую graphql-dataloader-template (https://github.com/sibelius/graphql-dataloader-boilerplate) в качестве тестового сервера. Просто запустите следующую команду, чтобы запустить ее

yarn run watch

7. Начните тесты.

yarn test

или проще:

jest

Совет: при написании теста вы можете использовать следующую команду для автоматического отслеживания изменений в файле, над которым вы работаете:

jest TestFileName --watch

Спасибо Григорию Пташко за эту замечательную идею.

Что дальше

  • Проверка мутаций реле
  • Тестирование изменения поведения переменных реле

Ресурсы

Вы также должны провести модульное тестирование своего GraphQL Backend



Вы также должны сделать свой GraphQL Backend безопасным -



Оформить заказ на мой шаблон GraphQL + DataLoader с 95% покрытием кода



Возникли проблемы с React Native + Relay - проверьте этот стартовый код:



Пытаюсь использовать ex-navigation с Relay - приступайте к работе



Новостная рассылка

Подпишитесь на мою рассылку для получения нового контента https://sibelius.substack.com/