Testing

Тестування Async Thunks

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

Тестування Async Thunks

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

Підхід 1: Mocking API Module

Найпростіший спосіб — замокати функцію, яка робить запит.

features/users/usersSlice.test.js
import { configureStore } from '@reduxjs/toolkit';
import usersReducer, { fetchUserById } from './usersSlice';
import * as api from '../../api/client'; // Припустимо, у нас є модуль API

// Мокаємо модуль
jest.mock('../../api/client');

describe('fetchUserById thunk', () => {
  it('should fetch user successfully', async () => {
    // 1. Налаштовуємо мок
    const mockUser = { id: 1, name: 'Ivan' };
    api.getUser.mockResolvedValue(mockUser);

    // 2. Створюємо store
    const store = configureStore({ reducer: { users: usersReducer } });

    // 3. Діспатчимо thunk
    await store.dispatch(fetchUserById(1));

    // 4. Перевіряємо стан
    const state = store.getState().users;
    expect(state.entities).toContainEqual(mockUser);
    expect(state.loading).toBe('succeeded');
  });

  it('should handle errors', async () => {
    // 1. Налаштовуємо мок на помилку
    api.getUser.mockRejectedValue(new Error('Network Error'));

    const store = configureStore({ reducer: { users: usersReducer } });

    await store.dispatch(fetchUserById(1));

    const state = store.getState().users;
    expect(state.loading).toBe('failed');
    expect(state.error).toBe('Network Error');
  });
});

Підхід 2: MSW (Mock Service Worker)

Це більш сучасний підхід. Ми перехоплюємо запити на рівні мережі. Це дозволяє тестувати код так, як він працює в реальності (через fetch).

import { setupServer } from 'msw/node';
import { rest } from 'msw';

// Налаштування сервера
const server = setupServer(
  rest.get('/api/users/1', (req, res, ctx) => {
    return res(ctx.json({ id: 1, name: 'Ivan' }));
  })
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

test('fetches user with MSW', async () => {
  const store = configureStore({ reducer: { users: usersReducer } });
  
  await store.dispatch(fetchUserById(1));
  
  expect(store.getState().users.entities[0].name).toBe('Ivan');
});

Висновок

Тестування Redux — це не "додаткова робота", а спосіб спати спокійно. Почніть з Unit тестів для рідюсерів (це найлегше), а потім додавайте інтеграційні тести для критичних сценаріїв.

👉 Повернутися до головного меню

Copyright © 2026