MobX интеграция в тесты

MobX — это библиотека для управления состоянием, которая активно используется в экосистеме React. Важно понимать, как правильно интегрировать MobX в тесты с использованием React Testing Library, поскольку это позволит создать эффективные и надёжные юнит-тесты для компонентов, работающих с MobX. Основной задачей является правильно моделировать состояние и эффективно тестировать взаимодействие компонентов с MobX-хранилищами.

MobX использует концепцию наблюдателей, которые следят за состоянием и автоматически обновляют компоненты при изменении данных. Это делает её отличным инструментом для реализации реактивных приложений. Однако при тестировании компонентов с MobX важен правильный подход к настройке тестового окружения, чтобы корректно эмулировать обновления состояния и рендеринг.

Подготовка окружения для тестирования MobX с React Testing Library

Перед тем как перейти к созданию тестов, нужно правильно настроить окружение. Это включает в себя установку нужных пакетов и настройку MobX и React Testing Library.

  1. Установка зависимостей:

    npm install @testing-library/react @testing-library/jest-dom @testing-library/user-event mobx mobx-react-lite
  2. Подключение MobX в компонент:

    Обычно компоненты, использующие MobX, должны быть обёрнуты в Observer, чтобы подписаться на изменения состояния. В React Testing Library важно правильно инкапсулировать компонент, чтобы он мог обновляться на основе изменений в MobX-хранилище.

Тестирование компонентов с MobX

Для тестирования компонентов, использующих MobX, потребуется создать простое MobX-хранилище и интегрировать его с React компонентами. Рассмотрим пример компонента, который использует MobX для управления состоянием.

Пример хранилища MobX

import { makeAutoObservable } from 'mobx';

class CounterStore {
  count = 0;

  constructor() {
    makeAutoObservable(this);
  }

  increment() {
    this.count++;
  }

  decrement() {
    this.count--;
  }
}

const counterStore = new CounterStore();
export default counterStore;

Пример компонента, использующего MobX

import React from 'react';
import { observer } from 'mobx-react-lite';
import counterStore from './counterStore';

const Counter = observer(() => (
  <div>
    <p>Count: {counterStore.count}</p>
    <button onCl ick={() => counterStore.increment()}>Increment</button>
    <button onCl ick={() => counterStore.decrement()}>Decrement</button>
  </div>
));

export default Counter;

Написание тестов для MobX-компонента

Для тестирования компонента с MobX важно правильно эмулировать изменения состояния и проверить, как они отражаются в UI. React Testing Library идеально подходит для проверки визуального представления компонентов, а для работы с MobX нужно будет учитывать асинхронные обновления.

Пример теста

import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
import counterStore from './counterStore';

describe('Counter', () => {
  test('отображает начальное значение count', () => {
    render(<Counter />);

    expect(screen.getByText(/Count: 0/i)).toBeInTheDocument();
  });

  test('увеличивает значение count при нажатии на кнопку', () => {
    render(<Counter />);

    fireEvent.click(screen.getByText(/Increment/i));
    expect(screen.getByText(/Count: 1/i)).toBeInTheDocument();
  });

  test('уменьшает значение count при нажатии на кнопку', () => {
    render(<Counter />);

    fireEvent.click(screen.getByText(/Decrement/i));
    expect(screen.getByText(/Count: -1/i)).toBeInTheDocument();
  });
});

В данном примере тестируются основные действия, такие как инкремент и декремент счётчика. После каждого действия компонент должен обновлять отображаемое значение. Тесты используют fireEvent для симуляции кликов на кнопки и screen.getByText для проверки текста на экране.

Асинхронные тесты с MobX

Если компоненты зависят от асинхронных операций или изменяются с задержкой, необходимо использовать асинхронные ожидания. React Testing Library предлагает метод findBy*, который позволяет ждать появления элементов на экране.

Пример асинхронного теста

Если MobX-хранилище выполняет асинхронную операцию, такую как загрузка данных, необходимо использовать асинхронные ожидания.

import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import Counter from './Counter';

test('должен обновить значение count после асинхронного действия', async () => {
  render(<Counter />);

  fireEvent.click(screen.getByText(/Increment/i));

  await waitFor(() => {
    expect(screen.getByText(/Count: 1/i)).toBeInTheDocument();
  });
});

Метод waitFor используется для того, чтобы подождать, пока произойдёт асинхронное обновление состояния в MobX, и затем проверить, что результат отобразился в компоненте.

Мокирование MobX-хранилища в тестах

Если нужно протестировать компонент, не используя реальное хранилище MobX, можно замокать его с помощью библиотек типа Jest.

Пример мокирования хранилища

import { render, screen, fireEvent } from '@testing-library/react';
import { observer } from 'mobx-react-lite';
import Counter from './Counter';

jest.mock('./counterStore', () => ({
  count: 0,
  increment: jest.fn(),
  decrement: jest.fn(),
}));

describe('Counter with mock store', () => {
  test('проверка мокированного хранилища', () => {
    render(<Counter />);

    fireEvent.click(screen.getByText(/Increment/i));
    expect(increment).toHaveBeenCalled();
  });
});

Мокирование позволяет тестировать компонент без зависимости от реального состояния и логики, что полезно, когда тестируемая часть приложения сильно связана с внешними состояниями.

Подведение итогов

Работа с MobX в тестах React-приложений требует нескольких важных подходов, таких как правильная настройка окружения, использование асинхронных методов и мокирование хранилищ для изоляции тестов. React Testing Library, в сочетании с MobX, предоставляет все необходимые инструменты для тестирования реактивных компонентов и их взаимодействий с состоянием.