Итак, история такова:
У меня есть компонент React. Я хочу провести юнит-тестирование рендеринга. Ранее я использовал поверхностное рендеринг с помощью enzyme и тестирование снимков для этой цели. Позвольте мне объяснить мои предпочтения, чтобы избежать повторений позже.
Почему снимки?
Потому что один тест “matchSnapshot” охватывает все проверки html одной строкой кода. Изменения снимка позже принимаются на код-ревью и проверяются командой. Мне это намного больше нравится, чем 20+ тестов, которые проверяют, что “<a> находится на странице”, “<a> href – это то”, “кнопка находится на странице”, “текст кнопки – это ‘submit'” и десятки подобных. Такие тесты раздувают кодовую базу. Единственный тест, который хуже – это expect(func).toBeDefined()
.
Почему поверхностный рендеринг?
Потому что это юнит-тест. Если вы делаете полный снимок, файл становится невероятно большим, его трудно проверять, и это приводит к ложным сбоям, когда внутреннее воплощение меняется. Если разработчик запускает тест и видит, что 200+ строк в снимке обновлено, обычно этот снимок отмечается как одобренный без проверки.
Я использую react-testing-library
с полным рендерингом для всего остального, кроме простых проверок структуры html. Я использую его для тестирования поведения пользователей, я использую его для тестирования сложных взаимодействий и ответов. Это идеально для этого.
К сожалению, с последним релизом enzyme, который вышел 5 лет назад, мне приходится писать очень многословные заглушки, чтобы добиться чистых небольших снимков.
vi.mock('@mui/joy/Button', () => ({
default: ({ children, ...rest }: React.PropsWithChildren) => <button {...rest}>{children}</button>
}))
vi.mock('@mui/joy/CardCover', () => ({
default: ({ children, ...rest }: React.PropsWithChildren) => <div {...rest}>{children}</div>
}))
// И еще 9 для каждого используемого компонента mui
Есть ли лучший способ? Способ потратить меньше времени на заглушки зависимостей, но все же получить чистые снимки?
Ответ
Чтобы выполнять легкое (shallow) тестирование компонентов в React 18 с использованием снимков (snapshot testing), вы можете воспользоваться библиотекой @testing-library/react
, которая более современна и активно поддерживается. Вот пошаговое руководство о том, как это сделать:
Шаг 1: Установка необходимых библиотек
Если у вас еще не установлены библиотеки для тестирования, вам нужно установить их. Используйте следующую команду:
npm install --save-dev @testing-library/react @testing-library/jest-dom jest
Шаг 2: Создание компонента
Допустим, у вас есть следующий компонент:
// MyComponent.jsx
import React from 'react';
import { Button } from '@mui/joy';
const MyComponent = () => {
return (
<div>
<h1>Hello World</h1>
<Button>Submit</Button>
</div>
);
};
export default MyComponent;
Шаг 3: Писать тест
Создайте файл теста, например, MyComponent.test.jsx
, и используйте следующее:
// MyComponent.test.jsx
import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';
// Мокаем внешние компоненты (если это необходимо)
jest.mock('@mui/joy/Button', () => {
return ({ children }) => <button>{children}</button>;
});
test('MyComponent snapshot', () => {
const { asFragment } = render(<MyComponent />);
// Сравниваем с ожидаемым снимком
expect(asFragment()).toMatchSnapshot();
});
Шаг 4: Запуск тестов
Запустите тесты с помощью команды:
npm test
Пояснения к решению
-
Преимущества использования
@testing-library/react
: Эта библиотека позволяет не только легко рендерить компоненты и делать снимки, но и предоставляет удобные методы для тестирования пользовательского взаимодействия. -
Мокание компонентов: В примере выше мы замокали компонент
Button
из@mui/joy
. Это поможет уменьшить "загрязнение" ваших снимков, так как вы контролируете, как компоненты отрисовываются. -
Снимок (snapshot): Метод
asFragment()
из@testing-library/react
возвращает DOM-элемент в виде фрагмента, который затем можно сравнить с сохраненным снимком. - Избегайте избыточности: Снимки могут отслеживать все изменения в структуре вашего компонента, но при этом вам не придется писать десятки отдельных ожиданий для каждого элемента.
Заключение
С использованием @testing-library/react
и jest
вы можете удобно и эффективно тестировать рендеринг ваших реактивных компонентов с минимальным количеством моков, при этом получая чистые снимки и избегая избыточной сложности в тестах. Этот подход соответствует вашим требованиям к тестированию, избегая проблем с большими снимками и трудоемкими моками.