简体   繁体   中英

NodeJs Testrunner freezes / stops when setting up Express server

I'm using Node v18 with the experimental testrunner. I use express as a dev dependency for http integration tests which works fine but there is one test freezing or stopping the testrunner ( it doesn't continue )

I'm using TS but can also reproduce it with JS, the test file HttpTests.js contains

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);
});

Running this with the npm script "test": "node --test $(find. -name '*Tests.js')" breaks the test runner.

Any ideas what is wrong or missing?


Why am I not using the default execution model ?

Since I'm using TS I had to find a way to use ts-node with the testrunner. You can find more information here

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

So currently my TS project is using this npm script, which works fine


Reproduction

I created a minimal reproduction repository with and without TypeScript

For reproduction purposes run mkdir reproduction && cd reproduction && npm init -y && npm install express . After that create a test directory with a file HttpTests.js containing the content as shown above. Change the package.json to

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

and run the script, the testrunner should not finish.


The testrunner is still experimental

Yes I know. But there are many tests in the project that work perfectly fine. Some sample code

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();
});

The issue is the async activity that you start ( server.listen() ) but don't stop before the test errors out (by an exception thrown by assert.ok(false) ).

Your second test case will probably also stall if actualResult doesn't deep-equal expectedResult because of the same issue ( server.close() won't be called).

A workaround would be to always make sure the server gets closed in the end:

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

Most test frameworks provide "before/after" functionality that can be used to set up or tear down auxiliary objects before and after a test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM