Моки та стабс у тестуванні React за допомогою Vite та Vitest

Тестування є невід'ємною частиною розробки фронтенд-додатків, адже воно допомагає виявити проблеми на ранніх етапах і уникнути багів до того, як код потрапить у продакшн. У цій статті йдеться про те, як проводити тестування в React-додатку, що використовує Vite та Vitest, а також про різницю між моками (mocks) і стабами (stubs), їх використання, а також як забезпечити високу якість тестів. Крім того, ми обговоримо, як штучний інтелект може допомогти в написанні тестів і як покращити їх за допомогою ШІ.

Vitest — це сучасний фреймворк для тестування, який ідеально працює з Vite. Він подібний до Jest, але швидший і краще інтегрований з інструментами, що використовують сучасний JavaScript та TypeScript. Vitest підтримує моки, стаби, тестування знімків (snapshot testing) та покриття коду. Якщо ви вже використовуєте Vite для вашого React-проєкту, Vitest стане ідеальним вибором. Оскільки він працює в тому ж середовищі, що й ваш додаток, це дозволяє отримувати швидкий зворотний зв'язок і покращує досвід розробника.

Тестування допомагає перевірити, чи працюють кнопки, чи правильно валідуються форми, чи правильно викликаються API, а також допомагає обробляти помилки, як-от збої в мережі. Тестування дає змогу переконатися, що ваш додаток працює в усіх ситуаціях, навіть якщо виглядає добре в браузері.

У тестуванні часто використовуються моки та стаби. Стуб — це проста фейкова функція, яка замінює реальну функцію та повертає фіксоване значення. Стуби використовуються, коли потрібно замінити тільки значення, яке повертає функція, без перевірки того, як і коли вона викликається. Наприклад, замість того, щоб звертатися до сервера під час тестування, можна замокати функцію, яка отримує дані.

Мок — це розширений варіант стуба, який не лише повертає фейкове значення, але й відстежує, як використовується функція. З його допомогою можна перевірити кількість викликів функції, які аргументи передавалися в неї та чи була вона взагалі викликана.

Використовуйте стуб тоді, коли вам потрібно лише замінити значення, яке повертає функція, а мок — коли потрібно перевіряти поведінку функції. Наприклад, для тестування кнопок чи форм з використанням моків можна перевірити, скільки разів була викликана функція.

Щоб створити хороші тести з Vitest, потрібно налаштувати тестове середовище. Для цього потрібно встановити vitest, @testing-library/react та jsdom:

npm install --save-dev vitest @testing-library/react jsdom

У конфігураційному файлі Vite потрібно додати тестову конфігурацію:

test: {
globals: true,
environment: "jsdom"
}

Далі потрібно продумати компонент, який ви хочете тестувати. Оскільки ми застосовуємо TDD (Test-Driven Development), спочатку розробляємо тест для компонента, а потім імплементуємо сам компонент. Також важливо подумати про логіку викликів API в окремих файлах, де буде використовуватися мок або стаб.

У Vitest для створення моків та стабів використовуються vi.fn() і vi.stub(). Наприклад:

// приклад мока
const mockFn = vi.fn().mockReturnValue("hello");

// приклад стаба
vi.stub(global, "fetch").returns(Promise.resolve({ json: () => Promise.resolve(data) }));

Кроки для написання тесту: після того, як ви налаштуєте середовище та визначите компонент, використовуйте @testing-library/react для рендерингу компонента, симулюйте дії користувача (наприклад, введення даних або натискання кнопок), а потім перевіряйте, чи правильно працюють моки та стаби.

Якісні тести мають перевіряти не лише правильність роботи коду, а й забезпечувати, що компонент працює так, як від нього очікується. Поради щодо написання хороших тестів:

  • Тестуйте лише важливі частини коду.
  • Використовуйте чіткі та зрозумілі назви для тестів.
  • Тримайте тести короткими — кожен тест має перевіряти одну функціональність.
  • Після кожного тесту очищуйте моки та стаби, щоб уникнути побічних ефектів.
  • Тестуйте також крайні випадки і помилки.

Підтримка ШІ допомагає пришвидшити процес написання тестів, особливо при створенні шаблонного коду. Проте важливо не покладатися лише на ШІ, а аналізувати, виправляти проблеми та переконатися, що тест справді відповідає логіці проєкту.

Моки і стаби використовуються для імітації зовнішніх функцій або API, щоб перевірити, як ваш додаток поводиться в різних ситуаціях. Наприклад, замокати виклик API за допомогою axios-mock-adapter дозволяє тестувати функції без реальних мережевих запитів:

const mockAxios = new MockAdapter(axios)

...

it('успішно виконує вхід і зберігає токени', async () => {
const mockResponse = {
accesstoken: 'test-access-token',
refresh
token: 'test-refresh-token',
}
mockAxios
.onPost(${config.API_ADMIN_URL}/admin-auth/login/)
.reply(200, mockResponse)

const result = await loginAdmin('testuser', 'testpassword')

expect(sessionStorageMock.setItem).toHaveBeenCalledWith(
'accesstoken',
'test-access-token'
)
expect(sessionStorageMock.setItem).toHaveBeenCalledWith(
'refresh
token',
'test-refresh-token'
)
expect(result).toEqual(mockResponse)
})

Цей підхід дозволяє контролювати поведінку функцій і API, зосереджуючи увагу на перевірці фронтенд-логіки, не виконуючи реальних мережевих запитів.

Тестування допомагає гарантувати, що ваш додаток працює правильно в усіх сценаріях, забезпечуючи високий рівень надійності та стабільності коду.

Перекладено з: Mocks vs. Stubs in React Testing with Vite and Vitest