Мокирование внешних зависимостей является неотъемлемой частью юнит-тестирования в JavaScript, в том числе при использовании Enzyme для тестирования компонентов React. Мокирование позволяет имитировать поведение зависимостей, чтобы сосредоточиться на тестировании компонента, а не на внешних библиотеках или API. В этой части рассмотрим, как правильно мокировать библиотеки в тестах с использованием Enzyme, а также основные подходы и инструменты для эффективного мокирования.
Мокирование — это процесс создания поддельных версий внешних зависимостей, которые имитируют их поведение. Это позволяет тестировать компонент в изоляции, не полагаясь на реальное поведение сложных зависимостей, таких как API-запросы, сторонние библиотеки или даже собственные модули, которые трудно или невозможно протестировать напрямую.
Мокирование помогает:
В экосистеме JavaScript существует несколько подходов к мокированию зависимостей. Основные из них:
Jest предлагает встроенные функции для мокирования модулей и
зависимостей, такие как jest.mock(), jest.fn()
и jest.spyOn(). Это позволяет создавать простые и гибкие
моки для любых зависимостей.
Для начала рассмотрим пример, когда компонент зависит от внешней
библиотеки, например, axios для выполнения
HTTP-запросов.
import React from 'react';
import { shallow } from 'enzyme';
import axios from 'axios';
import MyComponent from './MyComponent';
jest.mock('axios'); // Мокируем axios
describe('MyComponent', () => {
it('должен загрузить данные при монтировании', async () => {
const data = { response: 'success' };
axios.get.mockResolvedValue({ data }); // Мокируем успешный ответ
const wrapper = shallow(<MyComponent />);
await wrapper.instance().componentDidMount(); // Запуск компонента
expect(wrapper.state().data).toEqual(data);
});
});
В данном примере библиотека axios мокируется с помощью
jest.mock(), после чего мы задаем ожидаемое поведение с
помощью mockResolvedValue(). Это позволяет тестировать
компонент, не выполняя реальных HTTP-запросов.
Иногда необходимо мокировать не целые библиотеки, а только их
отдельные функции. В этом случае можно использовать
jest.fn(). Этот метод позволяет создать поддельную версию
функции с возможностью отслеживания её вызовов и возвращаемых
значений.
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('должен вызывать функцию при клике', () => {
const mockFunction = jest.fn(); // Создаем поддельную функцию
const wrapper = shallow(<MyComponent onCl ick={mockFunction} />);
wrapper.find('button').simulate('click'); // Симулируем клик
expect(mockFunction).toHaveBeenCalledTimes(1); // Проверяем, что функция вызвана один раз
});
});
В этом примере используется jest.fn() для мокирования
функции, передаваемой в компонент через пропсы. При клике на кнопку
вызывается мокированная функция, и затем проверяется, что она была
вызвана.
Sinon — это мощная библиотека для мокирования, шпионства и создания заглушек в JavaScript. Она может быть полезна, когда требуется больше контроля над поведением мока, например, для проверки вызовов функций или замены реальных методов.
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('должен вызывать функцию onClick', () => {
const onCl ick = sinon.spy(); // Создаем шпиона
const wrapper = shallow(<MyComponent onCl ick={onClick} />);
wrapper.find('button').simulate('click'); // Симулируем клик
expect(onClick.calledOnce).toBe(true); // Проверяем, что функция была вызвана один раз
});
});
Здесь мы использовали sinon.spy() для создания шпиона,
который отслеживает вызовы функции. После клика по кнопке проверяется,
что функция была вызвана.
Мокирование асинхронных операций, таких как HTTP-запросы или запросы
к базе данных, также играет важную роль в тестировании компонентов.
Обычно для этого используется jest.mock() с асинхронными
методами, такими как mockResolvedValue() или
mockRejectedValue().
import React from 'react';
import { shallow } from 'enzyme';
import axios from 'axios';
import MyComponent from './MyComponent';
jest.mock('axios'); // Мокируем axios
describe('MyComponent', () => {
it('должен обработать ошибку при неудачном запросе', async () => {
axios.get.mockRejectedValue(new Error('Ошибка сети')); // Мокируем ошибку
const wrapper = shallow(<MyComponent />);
await wrapper.instance().componentDidMount(); // Запуск компонента
expect(wrapper.state().error).toBe('Ошибка сети'); // Проверяем, что ошибка обработана
});
});
В этом примере мы мокируем ошибку, возникающую при запросе с помощью
mockRejectedValue(). Это позволяет убедиться, что компонент
правильно обрабатывает ошибки.
Enzyme предоставляет возможности для мокирования, хотя чаще всего это осуществляется с помощью Jest или Sinon в связке с Enzyme. Однако сам Enzyme предоставляет методы для работы с состоянием компонента, его методами и жизненным циклом, что важно при тестировании мокированных компонентов.
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('должен вызвать метод после монтирования', () => {
const mockMethod = jest.fn();
const wrapper = shallow(<MyComponent />);
wrapper.instance().someMethod = mockMethod; // Заменяем метод на мок
wrapper.instance().componentDidMount(); // Вызываем жизненный цикл
expect(mockMethod).toHaveBeenCalled(); // Проверяем вызов мока
});
});
Здесь происходит мокирование метода компонента, чтобы проверить его вызов в процессе жизненного цикла компонента.
Мокирование внешних зависимостей в Enzyme и Jest помогает изолировать
тестируемый компонент, улучшить тестируемость и повысить скорость
тестов. Для мокирования можно использовать различные подходы, включая
встроенные функции Jest (jest.mock(),
jest.fn(), mockResolvedValue()), а также
сторонние библиотеки, такие как Sinon. Важно помнить, что мокирование
должно быть использовано разумно, чтобы не создавать излишнюю сложность
в тестах, а лишь повысить их стабильность и предсказуемость.