У нас есть приложение, взаимодействующее с (Node.js) HTTP-сервером. Чтобы проверить вызовы API, мы создали тестовый HTTP-сервер, который отлично работает с приложением. Все вызовы, которые мы выполняем, ожидаются из приложения.
В последнее время мы тратим время, пытаясь автоматизировать тестирование этих вызовов API. Мы разработали одну стратегию:
- автоматический запуск тестового HTTP-сервера;
- выполнение вызовов на него;
- закрытие тестового HTTP-сервера после теста.
Вот как написан наш первый тест:
var serverHandler = require('../../server/serverHandler.js');
describe('Test the test server', function() {
beforeEach(async () => {
serverHandler.start(500, 'index.js'); // index.js: the HTTP test server.
// 500: 500 ms of latency to mimic a slow response.
result = await serverHandler.isRunning();
expect(result).toEqual(true);
});
afterEach(async () => {
serverHandler.kill();
result = await serverHandler.isRunning();
expect(result).toEqual(false);
});
test('Server is killed', async () => {
// We could have more complex test logic here...
serverHandler.kill();
try {
result = await serverHandler.isRunning();
expect(result).toEqual(false);
} catch (error) {
expect(error).toEqual({
error: 'server is running',
});
}
});
});
Где serverHandler
выглядит следующим образом:
const spawn = require('child_process').spawn;
const isReachable = require('is-reachable');
var child = null;
exports.start = (latency, path) => {
child = spawn('node', [path, latency]);
};
exports.kill = () => {
child.kill();
};
exports.isRunning = async () => {
return await isReachable('http://localhost:8080');
};
Как выКак видите, пока мы только пытаемся заставить шаги 1 и 3 работать, прежде чем добавлять тестовую логику. К сожалению, это не так. Когда я запускаю этот тест, я получаю следующий вывод:
● Test the test server › Server is killed
expect(received).toEqual(expected) // deep equality
Expected: true
Received: false
14 |
15 | result = await serverHandler.isRunning();
> 16 | expect(result).toEqual(true);
| ^
17 | });
18 |
19 | afterEach(async () => {
at toEqual (__tests__/integration/serverIntegrationExample.test.js:16:20)
at tryCatch (node_modules/regenerator-runtime/runtime.js:45:40)
at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:271:22)
at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:97:21)
at tryCatch (node_modules/regenerator-runtime/runtime.js:45:40)
at invoke (node_modules/regenerator-runtime/runtime.js:135:20)
at node_modules/regenerator-runtime/runtime.js:145:13
at tryCallOne (node_modules/promise/lib/core.js:37:12)
at node_modules/promise/lib/core.js:123:15
at flush (node_modules/asap/raw.js:50:29)
Похоже, сервер фактически никогда не запускается. Я знаю, что тестовый сервер работает хорошо, потому что все вызовы успешно выполняются в приложении. Я обнаружил различные источники, говорящие о похожих проблемах, но большинство из них, похоже, либо тупиковые, либо используют непереносимые функции ОС, что для нас неприемлемо (я получаю этот вывод из Ubuntu).
В чем (с) проблема (ы) в этом коде и как мне этого добиться? Также обратите внимание, что это мой первый проект Node.js, поэтому любые конструктивные советы по коду будут приняты с благодарностью.
EDIT
Вот код для index.js
:
const Express = require('express');
const multer = require('multer');
const bodyParser = require('body-parser');
const fs = require('fs');
const labelListMock = require('./mockData');
const uploadDirectory = './images';
const app = Express();
app.use(bodyParser.json());
const Storage = multer.diskStorage({
destination(req, file, callback) {
callback(null, uploadDirectory);
},
filename(req, file, callback) {
callback(null, `${file.fieldname}_${Date.now()}_${file.originalname}`);
},
});
const upload = multer({storage: Storage});
app.get('/', (req, res) => {
res.status(200).send('You can post to /DispatchData.');
});
var latency = process.argv[2];
if (isNaN(latency)) {
latency = 0;
}
app.use(function(req, res, next) {
setTimeout(next, latency);
});
app.get('/RetrieveTypes', (req, res) => {
res.status(200).json(labelListMock);
});
app.post(
'/DispatchData',
checkUploadPath,
upload.single('photo'),
(req, res, next) => {
console.log('file', req.file);
console.log('body', req.body);
res.status(200).json({
message: 'success!',
fileName: req.file.originalname,
category: 'buildAILabel',
});
},
);
module.exports = app.listen(8080, () => {
console.log(
'Mock server running on http://localhost:8080 (or http:://10.0.2.2:8080 if using an emulator.)',
);
});
function checkUploadPath(req, res, next) {
fs.exists(uploadDirectory, function(exists) {
if (exists) {
next();
} else {
fs.mkdir(uploadDirectory, function(err) {
if (err) {
console.log('Error in folder creation');
next();
}
next();
});
}
});
}