Karma является инструментом для запуска тестов JavaScript в реальном браузере. Одной из ключевых возможностей Karma является использование HTTP middleware, которое позволяет перехватывать, модифицировать или обслуживать HTTP-запросы, поступающие от браузера, во время выполнения тестов. Это особенно важно при тестировании приложений с асинхронными запросами или при необходимости имитации серверной логики.
Установка Karma выполняется через npm:
npm install --save-dev karma karma-cli
Для работы с middleware необходимо подключить серверный компонент
Karma — karma-server. Middleware в Karma регистрируется
в конфигурационном файле karma.conf.js через опцию
middleware и обрабатывается через массив функций,
возвращающих обработчик (req, res, next).
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
files: [
'src/**/*.js',
'test/**/*.spec.js'
],
middleware: ['mockServer'],
plugins: [
'karma-jasmine',
'karma-chrome-launcher',
{
'middleware:mockServer': ['factory', function() {
return function(req, res, next) {
if (req.url === '/api/data') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Hello from mock server' }));
} else {
next();
}
};
}]
}
]
});
};
В этом примере создается псевдосервер, который
перехватывает запросы к /api/data и возвращает статический
JSON. Все остальные запросы передаются дальше по цепочке через
next().
Middleware в Karma представляют собой обычные функции Node.js, принимающие три аргумента:
Пример расширенного middleware:
function loggingMiddleware(req, res, next) {
console.log(`[Karma Middleware] ${req.method} ${req.url}`);
next();
}
Такое middleware удобно использовать для логирования запросов и отладки тестов, особенно если в проекте много асинхронных HTTP вызовов.
Karma позволяет подключать несколько middleware одновременно. Они выполняются в том порядке, в котором перечислены в конфигурации:
middleware: ['logger', 'mockApi', 'corsHandler'],
plugins: [
{
'middleware:logger': ['factory', () => (req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
}],
},
{
'middleware:mockApi': ['factory', () => (req, res, next) => {
if (req.url.startsWith('/api')) {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok' }));
} else next();
}],
},
{
'middleware:corsHandler': ['factory', () => (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
}],
}
]
Такой подход обеспечивает модульность и упрощает поддержку сложной цепочки обработки запросов.
Middleware могут выполнять асинхронные действия, например чтение файлов или запросы к внешним сервисам. Для корректной работы необходимо убедиться, что ответ отправляется после завершения всех асинхронных операций:
const fs = require('fs').promises;
function fileMiddleware(req, res, next) {
if (req.url === '/mock/file') {
fs.readFile('./mock/data.json', 'utf-8')
.then(data => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(data);
})
.catch(err => {
res.writeHead(500);
res.end('Internal Server Error');
});
} else {
next();
}
}
Асинхронная обработка позволяет точно имитировать задержку сервера и проверять поведение клиента при различных сценариях.
Middleware напрямую влияет на тесты, поскольку браузер, запущенный через Karma, обращается к локальному серверу Karma для загрузки файлов и API-запросов. В Jasmine или Mocha тестах можно проверять поведение кода при разных ответах сервера:
describe('API Mock Test', () => {
it('should return mock data', async () => {
const response = await fetch('/api/data');
const data = await response.json();
expect(data.message).toBe('Hello from mock server');
});
});
Использование middleware позволяет изолировать тестируемый код от внешнего API, ускоряет тестирование и делает его более предсказуемым.
Karma поддерживает горячую замену middleware через
config.set во время работы сервера. Это полезно для
тестирования различных сценариев без перезапуска Karma:
server.on('request', (req, res) => {
if (req.url === '/toggle') {
config.set({
middleware: ['alternateMock']
});
}
});
Такой подход облегчает проверку нескольких вариантов поведения API в рамках одного запуска тестов.
next() для необработанных
запросов.require, чтобы конфигурация оставалась чистой.Такой подход позволяет создавать надежную и расширяемую инфраструктуру для тестирования HTTP-запросов в приложениях JavaScript.