Skip to main content
Практика завдань

Як протестувати додаток Express.js?

Тестування додатків Express.js

Тестування додатків Express передбачає модульні тести для окремих функцій та інтеграційні тести для повного циклу запиту/відповіді HTTP. Ключовим інструментом є Supertest — він здійснює реальні HTTP запити до вашого додатку без запуску сервера.


Налаштування

bash
npm install --save-dev jest supertest # або з TypeScript: npm install --save-dev jest supertest @types/jest @types/supertest ts-jest

Структура додатку для тестування

Відокремте ваш додаток Express від запуску сервера:

js
// app.js — експортуйте app, без listen() const express = require('express'); const app = express(); app.use(express.json()); app.use('/users', usersRouter); module.exports = app; // server.js — тільки цей файл викликає listen() const app = require('./app'); app.listen(3000);

Інтеграційні тести з Supertest

js
// users.test.js const request = require('supertest'); const app = require('../app'); describe('Users API', () => { describe('GET /users', () => { it('повинен повернути 200 та масив користувачів', async () => { const res = await request(app).get('/users'); expect(res.status).toBe(200); expect(res.body).toHaveProperty('data'); expect(Array.isArray(res.body.data)).toBe(true); }); }); describe('POST /users', () => { it('повинен створити користувача та повернути 201', async () => { const res = await request(app) .post('/users') .send({ name: 'Alice', email: 'alice@test.com' }); expect(res.status).toBe(201); expect(res.body.data.name).toBe('Alice'); }); it('повинен повернути 400, коли відсутній email', async () => { const res = await request(app) .post('/users') .send({ name: 'Alice' }); // без email! expect(res.status).toBe(400); expect(res.body).toHaveProperty('error'); }); }); describe('GET /users/:id', () => { it('повинен повернути 404 для неіснуючого користувача', async () => { const res = await request(app).get('/users/9999'); expect(res.status).toBe(404); }); }); });

Тестування захищених маршрутів

js
const jwt = require('jsonwebtoken'); function generateTestToken(payload = { id: 1, role: 'user' }) { return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' }); } describe('Захищені маршрути', () => { it('повинен повернути 401 без токена', async () => { const res = await request(app).get('/profile'); expect(res.status).toBe(401); }); it('повинен повернути 200 з дійсним токеном', async () => { const token = generateTestToken(); const res = await request(app) .get('/profile') .set('Authorization', `Bearer ${token}`); expect(res.status).toBe(200); }); });

Мокінг сервісів

js
// Мокінг шару бази даних jest.mock('../services/users.service', () => ({ findAll: jest.fn().mockResolvedValue([ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]), findById: jest.fn().mockResolvedValue({ id: 1, name: 'Alice' }), create: jest.fn().mockResolvedValue({ id: 3, name: 'Charlie' }) })); const usersService = require('../services/users.service'); it('повинен викликати service.findAll один раз', async () => { await request(app).get('/users'); expect(usersService.findAll).toHaveBeenCalledTimes(1); });

Стратегія тестової бази даних

ПідхідШвидкістьІзоляціяРеалістичність
Мокінг шару сервісівНайшвидшийВисокаНизька
База даних в пам'яті (SQLite)ШвидкаСередняСередня
Тестова база данихПовільнішаНизька (потребує очищення)Висока
Контейнер DockerНайповільнішийВисокаНайвища

jest.config.js

js
module.exports = { testEnvironment: 'node', setupFilesAfterEach: ['./jest.setup.js'], coveragePathIgnorePatterns: ['/node_modules/'], };

Резюме

Використовуйте Supertest + Jest для тестування додатків Express. Тримайте ваш додаток у app.js (без listen()) для того, щоб тести могли імпортувати його безпосередньо. Тестуйте повний цикл HTTP: коди статусу, тіло відповіді, заголовки та аутентифікацію. Мокінг шару бази даних/сервісів для швидких, ізольованих модульних тестів.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань