Тестування Async Thunks
Тестування Async Thunks
Тестування асинхронних операцій вимагає контролю над мережевими запитами. Ми не хочемо робити реальні запити на бекенд під час тестів.
Підхід 1: Mocking API Module
Найпростіший спосіб — замокати функцію, яка робить запит.
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 тестів для рідюсерів (це найлегше), а потім додавайте інтеграційні тести для критичних сценаріїв.
Тестування Компонентів (Integration)
Коли компонент використовує useSelector або useDispatch, ми не можемо просто відрендерити його в тесті. Він впаде з помилкою could not find react-redux context value.
UI Бібліотеки в React
Модуль присвячений вивченню сучасних UI бібліотек для React, з детальним фокусом на shadcn/ui — інноваційний підхід до створення компонентних систем.