MobX — это библиотека для управления состоянием, которая активно используется в экосистеме React. Важно понимать, как правильно интегрировать MobX в тесты с использованием React Testing Library, поскольку это позволит создать эффективные и надёжные юнит-тесты для компонентов, работающих с MobX. Основной задачей является правильно моделировать состояние и эффективно тестировать взаимодействие компонентов с MobX-хранилищами.
MobX использует концепцию наблюдателей, которые следят за состоянием и автоматически обновляют компоненты при изменении данных. Это делает её отличным инструментом для реализации реактивных приложений. Однако при тестировании компонентов с MobX важен правильный подход к настройке тестового окружения, чтобы корректно эмулировать обновления состояния и рендеринг.
Перед тем как перейти к созданию тестов, нужно правильно настроить окружение. Это включает в себя установку нужных пакетов и настройку MobX и React Testing Library.
Установка зависимостей:
npm install @testing-library/react @testing-library/jest-dom @testing-library/user-event mobx mobx-react-liteПодключение MobX в компонент:
Обычно компоненты, использующие MobX, должны быть обёрнуты в
Observer, чтобы подписаться на изменения состояния. В React
Testing Library важно правильно инкапсулировать компонент, чтобы он мог
обновляться на основе изменений в MobX-хранилище.
Для тестирования компонентов, использующих MobX, потребуется создать простое MobX-хранилище и интегрировать его с React компонентами. Рассмотрим пример компонента, который использует 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;
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 важно правильно эмулировать изменения состояния и проверить, как они отражаются в 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 для проверки
текста на экране.
Если компоненты зависят от асинхронных операций или изменяются с
задержкой, необходимо использовать асинхронные ожидания. 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, можно замокать его с помощью библиотек типа 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, предоставляет все необходимые инструменты для тестирования реактивных компонентов и их взаимодействий с состоянием.