Як я можу програмно відключити екземпляр ExpressJS для тестування?


106

Я намагаюся розібратися, як закрити екземпляр Express. В основному, я хочу зворотний .listen(port)виклик - як мені змусити сервер Експрес зупинитися на прослуховуванні, звільнити порт і закрити чисто?

Я знаю, це здається, що це може бути дивним запитом, тож ось контекст; можливо, є інший спосіб підійти до цього, і я думаю про це неправильно. Я намагаюся налаштувати тестову основу для свого додатка socket.io/nodejs. Це односторінковий додаток, тому в моїх сценаріях тестування (я використовую Mocha, але це насправді не має значення) Я хочу мати змогу запустити сервер, запустити тести проти нього, а потім закрити сервер. Я можу обійти це, якщо припустити, що або сервер увімкнено перед початком тесту, або запустивши один із тестів, і кожен наступний тест припускає, що це працює, але це справді безлад. Я б хотів би, щоб кожен тестовий файл запустив екземпляр сервера з відповідними налаштуваннями, а потім закрив цей екземпляр, коли тести закінчаться. Це означає, що немає дивних залежностей від запуску тесту, і все чисто. Це також означає, що я можу зробити тестування запуску / відключення.

Отже, будь-яка порада, як це зробити? Я думав над тим, щоб вручну викликати винятки, щоб їх знищити, але це здається безладним. Я переглянув документи Express і джерело, але не можу знайти жодного методу, який би закрив сервер. Для цього може бути і щось у socket.io, але оскільки сервер сокет якраз приєднаний до сервера Express, я думаю, що це має відбуватися на рівні експресів.

Відповіді:


156

Все змінилося, тому що експрес-сервер більше не успадковує з сервера http сервера. На щастя, app.listen повертає екземпляр сервера.

var server = app.listen(3000);

// listen for an event
var handler = function() {
  server.close();
};

23
У випадку тестування Mocha, де вам потрібно ("додаток"), я поширююся на об’єкт програми: app.server = app.listen (3000); тому пізніше я можу сказати: var app = Require ('./ app'); app.server.close ();
Джек Чі

2
під час тестування сервера перевіряйте github.com/visionmedia/supertest, це дозволить вам протестувати без запуску фактичного сервера
Lukas Liesis

Я б також запропонував вам передати готовий зворотний дзвінок, server.close()якщо дзвоніть це з гачка.
Уллаурі

Примітка. Існує велика різниця між "app", що є екземпляром Express Application, і зворотним значенням "app.listen", що є основним базовим екземпляром сервера HTTP, який має метод "close". @JackChi натякнув на це вище.
ajxs

Це не викликає проблем із відкритими розетками клієнта, які залишаються відкритими?
Камерон Таклінд

18

Використовуйте app.close(). Повний приклад:

var app = require('express').createServer();
app.get('/', function(req, res){
  res.send('hello world');
});
app.get('/quit', function(req,res) {
  res.send('closing..');
  app.close();
});
app.listen(3000);

Виклик app.close()всередині зворотного дзвінка, коли тести закінчилися. Але пам’ятайте, що процес все ще працює (хоч він уже не слухається).

Якщо після цього вам потрібно закінчити процес, тоді зателефонуйте process.exit(0).

Посилання:

app.close: http://nodejs.org/docs/latest/api/http.html#server.close (те саме стосується)

process.exit: http://nodejs.org/docs/latest/api/process.html#process.exit


1
Ідеально, саме те, що я шукав. Напевно, я не знайшов його в Express, тому що вони розширювали сервер http http сервера, який я не повністю розумів. Дякую!
drewww

Дякую Сріане, і це мені допомогло
Адам Хопкінсон

Це все-таки правда? express.createServer позначає як застаріле, і видає помилку, кажучи, що додаток більше не успадковує сервер
http.js

4
Це не
вірно,

4
Розкриття такої URL-адреси для закриття сервера, як ІМХО, це не дуже гарна ідея.
shime

2

Я багато разів відповідав на варіацію "як припинити роботу HTTP-сервера" на різних канали підтримки. На жаль, я не міг рекомендувати жодну з існуючих бібліотек, оскільки їх так чи інакше бракує . З тих пір я зібрав пакет, який (я вважаю) розглядає всі випадки очікування витонченого завершення сервера HTTP.

https://github.com/gajus/http-terminator

Основна перевага http-термінатора полягає в тому, що:

  • це не мавпа-патч API Node.js
  • він негайно знищує всі сокети без доданого запиту HTTP
  • це дозволяє витончений тайм-аут на розетки з поточними HTTP-запитами
  • він належним чином обробляє HTTPS-з'єднання
  • він повідомляє про з'єднання за допомогою режиму "Keep-Live", що сервер вимикається, встановивши з'єднання: закрити заголовок
  • він не завершує процес Node.js

Використання з Express.js:

import express from 'express';
import {
  createHttpTerminator,
} from 'http-terminator';

const app = express();

const server = app.listen();

const httpTerminator = createHttpTerminator({
  server,
});

await httpTerminator.terminate();


-1

Ви можете легко зробити це, написавши bash-скрипт для запуску сервера, запуску тестів і зупинки сервера. Це має перевагу в тому, що ви можете псевдонімом цього сценарію швидко і легко запускати всі ваші тести.

Я використовую такі сценарії протягом усього безперервного процесу розгортання. Ви можете подивитися на "Dead Simple Git Workflow" Джона Рохана, щоб дізнатися про це.


2
Це спрацювало б, але я вважаю за краще рішення, яке не вимагає. Можливо, це дурне уподобання, але я хотів би запускати / зупиняти сервер із тестового контексту, оскільки це спрощує написання тестів, визначених для сервера та конфігурації + тести запуску / вимикання. Крім того, він не вводить опосередкованість необхідності запускати тести, пов’язані з сервером, за допомогою окремого сценарію.
drewww

Чому ви пишете тести, що стосуються середовища? Можливо, я помиляюся, але це вважає мене поганою практикою. Я б спробував залишатись агресивним середовищем з вашим тестуванням, так як ви хочете, щоб ваші тести працювали у вашій команді незалежно від середовища їх розробки.
Джош Сміт

Я не роблю тут нічого конкретного середовища, я не думаю. Буде кілька варіантів запуску для сервера (наприклад, читання параметрів конфігурації з файлу, стан завантаження з сховища даних тощо), що було б непогано перевірити в тій самій рамці, що я перевіряю все інше. Я також хотів би провести тести, які, наприклад, вимкнути сервер, повернути його знову і переконатися, що він не втратив стан у процесі. Це простіше, якщо я можу це зробити програмно з вузла, ніж тестування коду в bash.
drewww

Ви б не помістили свій тестовий код у сам баш. Ви б просто запустити сервер і запустити тести зі скрипту так само, як і в командному рядку. Там немає справжньої особливої ​​магії.
Джош Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.