5.1 Знакомство с интеграционным тестированием
Интеграционное тестирование (integration testing) — это этап тестирования, при котором проверяется взаимодействие между различными модулями или компонентами системы. Цель интеграционного тестирования — убедиться, что модули системы работают корректно вместе и что их взаимодействие соответствует ожиданиям.
Ниже мы рассмотрим настройку интеграционного тестирования для TypeScript проектов с использованием популярных инструментов, таких как Jest и Supertest, и приведем примеры.
Зачем нужно интеграционное тестирование?
- Выявление проблем на уровне взаимодействия модулей: интеграционное тестирование помогает выявить проблемы, которые возникают не в отдельных модулях, а при их взаимодействии.
- Уверенность в корректности работы системы: проверка взаимодействия модулей дает уверенность в том, что система работает корректно в реальных условиях.
- Обнаружение регрессий: интеграционные тесты помогают обнаружить регрессии, которые могут возникнуть при изменении кода.
5.2 Настройка интеграционного тестирования
Для настройки интеграционного тестирования в TypeScript проектах мы будем использовать Jest и Supertest. Jest — это мощный фреймворк для тестирования, а Supertest — это библиотека для тестирования HTTP-сервисов.
1. Установка зависимостей
Начнем с установки необходимых зависимостей:
npm install --save-dev jest ts-jest @types/jest supertest @types/supertest typescript
2. Создание конфигурационного файла TypeScript
Создайте файл tsconfig.json в корне проекта:
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["src"],
"exclude": ["node_modules"]
}
3. Создание конфигурационного файла Jest
Создайте файл jest.config.js в корне проекта:
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
};
4. Создание структуры проекта
Создайте папку src для исходного кода и папку tests для тестов:
mkdir src
mkdir tests
5.3 Пример интеграционного тестирования
Рассмотрим пример простого REST API на основе Express и напишем интеграционные тесты для него.
1. Создание Express приложения
Создайте файл src/app.ts с простым Express приложением:
import express from 'express';
const app = express();
app.use(express.json());
app.get('/hello', (req, res) => {
res.json({ message: 'Hello, World!' });
});
app.post('/echo', (req, res) => {
res.json({ message: req.body.message });
});
export default app;
2. Создание файла для запуска сервера
Создайте файл src/server.ts для запуска сервера:
import app from './app';
const port = 3000;
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
3. Написание интеграционных тестов
Создайте файл tests/app.test.ts с интеграционными тестами:
import request from 'supertest';
import app from '../src/app';
describe('GET /hello', () => {
it('should return a greeting message', async () => {
const response = await request(app).get('/hello');
expect(response.status).toBe(200);
expect(response.body.message).toBe('Hello, World!');
});
});
describe('POST /echo', () => {
it('should echo the message sent in the request body', async () => {
const message = 'Hello, Jest!';
const response = await request(app).post('/echo').send({ message });
expect(response.status).toBe(200);
expect(response.body.message).toBe(message);
});
});
4. Запуск тестов
Добавьте скрипт для запуска тестов в package.json:
"scripts": {
"test": "jest"
}
Запустите тесты командой:
npm test
Jest выполнит тесты и выведет результаты в консоли.
5.4 Продвинутые примеры интеграционного тестирования
1. Тестирование с использованием базы данных
Рассмотрим пример, где мы добавим использование базы данных для тестирования CRUD операций. Используем SQLite как in-memory базу данных для тестов.
Установите необходимые зависимости:
npm install --save-dev sqlite3 typeorm @types/sqlite3
Настроим TypeORM для работы с SQLite. Создайте файл src/entity/User.ts для определения сущности пользователя:
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
email: string;
}
Создайте файл src/dataSource.ts для настройки подключения к базе данных:
import { DataSource } from 'typeorm';
import { User } from './entity/User';
export const AppDataSource = new DataSource({
type: 'sqlite',
database: ':memory:',
dropSchema: true,
entities: [User],
synchronize: true,
logging: false,
});
AppDataSource.initialize()
.then(() => {
console.log('Data Source has been initialized!');
})
.catch((err) => {
console.error('Error during Data Source initialization:', err);
});
Обновите файл src/app.ts для использования базы данных:
import express from 'express';
import { AppDataSource } from './dataSource';
import { User } from './entity/User';
const app = express();
app.use(express.json());
app.get('/users', async (req, res) => {
const users = await AppDataSource.getRepository(User).find();
res.json(users);
});
app.post('/users', async (req, res) => {
const user = AppDataSource.getRepository(User).create(req.body);
const result = await AppDataSource.getRepository(User).save(user);
res.json(result);
});
export default app;
Создайте интеграционные тесты для работы с пользователями в файле tests/users.test.ts:
import request from 'supertest';
import app from '../src/app';
import { AppDataSource } from '../src/dataSource';
import { User } from '../src/entity/User';
beforeAll(async () => {
await AppDataSource.initialize();
});
afterAll(async () => {
await AppDataSource.destroy();
});
describe('User API', () => {
it('should create a new user', async () => {
const newUser = { name: 'John Doe', email: 'john@example.com' };
const response = await request(app).post('/users').send(newUser);
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('id');
expect(response.body.name).toBe(newUser.name);
expect(response.body.email).toBe(newUser.email);
});
it('should get all users', async () => {
const response = await request(app).get('/users');
expect(response.status).toBe(200);
expect(response.body.length).toBeGreaterThan(0);
});
});
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ