Búsqueda de sitios web

javascript - NodeJs Testrunner se congela/se detiene al configurar el servidor Express


Estoy usando Node v18 con el testrunner experimental. Uso express como una dependencia de desarrollo para pruebas de integración HTTP, lo cual funciona bien, pero hay una prueba que se congela o detiene el testrunner (no continúa)

Estoy usando TS pero también puedo reproducirlo con JS, el archivo de prueba HttpTests.js contiene

import assert from 'assert/strict';
import express from 'express';
import test from 'node:test';

test('Http', async () => {
  const server = express();
    
  server.listen(3000);
  assert.ok(false);
});

Ejecutar esto con el script de npm "test": "node --test $ (find . -name '*Tests.js')" rompe el ejecutor de pruebas.

¿Alguna idea de qué está mal o qué falta?


¿Por qué no estoy usando el modelo de ejecución predeterminado?

Dado que estoy usando TS, tuve que encontrar una manera de usar ts-node con el corredor de pruebas. Puedes encontrar más información aquí

https://github.com/nodejs/node/issues/43675

Así que actualmente mi proyecto de TS está usando este script de npm, que funciona bien


Reproducción

Creé un repositorio de reproducción mínima con y sin TypeScript

  • https://github.com/matthiashermsen/reproduce-broken-test-ts
  • https://github.com/matthiashermsen/reproduce-broken-test-js

Para fines de reproducción, ejecute mkdir reproduction && cd reproduction && npm init -y && npm install express. Después de eso, cree un directorio test con un archivo HttpTests.js que contenga el contenido como se muestra arriba. Cambie el package.json a

{
  "name": "reproduction",
  "type": "module",
  "scripts": {
    "test": "node --test $(find . -name '*Tests.js')"
  }
}

y ejecutar el script, el corredor de pruebas no debería terminar.


El ejecutor de pruebas todavía es experimental

Sí, lo sé. Pero hay muchas pruebas en el proyecto que funcionan perfectamente. Algo de código de ejemplo

await t.test('subtest - saves data.', async () => {
    const expectedResult = {};
  
    const api = express();
    const port = await getRandomPort();
    const server = api
        .use(express.json())
        .post('/save', (request, response) => {
            response.json(expectedResult);
        })
        .listen(port);

    const httpDataProvider = new HttpDataProvider({ url: `http://localhost:${port}` });
    const actualResult = await httpDataProvider.saveSomething();

    assert.deepEqual(actualResult, expectedResult);

    server.close();
});

Respuesta #1

El problema es la actividad asíncrona que inicias (server.listen()) pero no detienes antes de que la prueba falle (por una excepción lanzada por assert.ok(false)).

Tu segundo caso de prueba probablemente también se detendrá si actualResult no es profundamente igual a expectedResult debido al mismo problema (server.close() no se llamará).

Una solución alternativa sería asegurarse siempre de que el servidor se cierre al final:

test('Http', async () => {
  const app    = express();
  const server = app.listen(3000);
  try {
    assert.ok(false);
  } finally {
    server.close();
  }
});

La mayoría de los frameworks de pruebas proporcionan funcionalidad de "antes/después" que se puede usar para configurar o desmantelar objetos auxiliares antes y después de una prueba.