'app.address is not a function' 测试快速 HTTPS 服务器时

'app.address is not a function' when testing an express HTTPS server

我在测试我的 express 应用程序时遇到了问题 运行。所有教程都使用 app.listen 而不是 https.createServer,我不知道如何正确使用后者的测试框架。代码:

test_node/app.js

var express = require("express");
const app = express();

app.set('port', process.env.SERVER_PORT || 443);
app.get('/', function(req, res){
    res.status(200).send('OK');
});

module.exports = {
    app: app
}

test_node/server.js

var https = require('https');
var fs = require('fs');
const app = require('./app');

let serverOptions = {
    key: fs.readFileSync('./cert/server.key'),
    cert: fs.readFileSync('./cert/server.cert')
}
const server = https.createServer(serverOptions, app)
server.listen(app.get('port'), function () {
    console.log(`Express HTTPS server listening on port ${app.get('port')}`);
});

async function handleSignal(signal) {
    console.log(`Received ${signal}`);
    server.close();
    process.exit();
}
process.on('SIGINT', handleSignal);
process.on('SIGTERM', handleSignal);
process.on('uncaughtException', handleSignal);

test_node/test/test.js

const request = require('supertest')

describe("Test the root path", () => {
    let server;
    beforeAll(function () {
        server = require('../app');
    });
    afterAll(function () {
        server.close();
    });

    test("It should respond to the GET method", async () => {
        const response = await request(server).get("/");
        expect(response.statusCode).toBe(200);
    });
});

test_node/package.json

{
  "name": "test_node",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "node server.js",
    "test": "jest"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "jest": "^26.6.3",
    "supertest": "^6.1.3"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}

我用 jest (jest --runInBand test.js) 测试上面的代码时得到的错误:

TypeError: app.address is not a function
    at Test.Object.<anonymous>.Test.serverAddress (C:\code\test_node\node_modules\supertest\lib\test.js:57:18)
    at new Test (C:\code\test_node\node_modules\supertest\lib\test.js:38:12)
    at Object.get (C:\code\test_node\node_modules\supertest\index.js:27:14)
    at Object.<anonymous> (C:\code\test_node\test\test.js:13:48)
    at Object.asyncJestTest (C:\code\test_node\node_modules\jest-jasmine2\build\jasmineAsyncInstall.js:106:37)
    at C:\code\test_node\node_modules\jest-jasmine2\build\queueRunner.js:45:12
    at new Promise (<anonymous>)
    at mapper (C:\code\test_node\node_modules\jest-jasmine2\build\queueRunner.js:28:19)
    at C:\code\test_node\node_modules\jest-jasmine2\build\queueRunner.js:75:41

这显然是我的代码的精简版。我还在开始时创建了 MongoDB 个连接,但为了简单起见,我删除了它们。理想情况下,我想在测试开始之前使用 async/await 而不是 promises 来创建我的服务器(和 MongoDB 连接)。我还需要在测试结束或失败后关闭这些连接。在您的回答中,您可以放心地假设我是 JS 初学者 :).

附加信息

我在 Windows 10 x64 上使用节点“14.15.4”。网络风暴 IDE.

尝试了以下各种组合:

我遇到的错误取决于我尝试的组合:

没有帮助的相关主题(或者我忽略了什么):

上下文

我在上面包含了server.js文件,虽然测试没有使用它,因为我的服务器应用程序在我运行 node server.js时应该也能正常启动。使用上面的代码它没有启动,我收到以下错误:

events.js:112
    throw new ERR_INVALID_ARG_TYPE('listener', 'Function', listener);
    ^

TypeError [ERR_INVALID_ARG_TYPE]: The "listener" argument must be of type function. Received an instance of Object
    at checkListener (events.js:112:11)
    at _addListener (events.js:348:3)
    at Server.addListener (events.js:406:10)
    at new Server (https.js:71:10)
    at Object.createServer (https.js:91:10)
    at Object.<anonymous> (C:\code\test_node\server.js:9:22)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14) {
  code: 'ERR_INVALID_ARG_TYPE'
}

但是,如果我将所有代码放在同一个 app.js 文件中并且我 运行 node app.js,那么应用程序可以正常启动,尽管测试会产生相同的错误。

test_node/app.js

var https = require('https');
var fs = require('fs');
var express = require("express");
var server;
const app = express();

app.set('port', process.env.SERVER_PORT || 443);
app.get('/', function(req, res){
    res.status(200).send('OK');
});

async function handleSignal(signal) {
    console.log(`Received ${signal}`);
    server.close();
    process.exit();
}
process.on('SIGINT', handleSignal);
process.on('SIGTERM', handleSignal);
process.on('uncaughtException', handleSignal);

let serverOptions = {
    key: fs.readFileSync('./cert/server.key'),
    cert: fs.readFileSync('./cert/server.cert')
}
server = https.createServer(serverOptions, app).listen(app.get('port'), function () {
        console.log(`Express HTTPS server listening on port ${app.get('port')}`);
    });

module.exports = {
    app: app,
    server: server
}

澄清一下,我的问题是如何修复玩笑测试中的错误,而不是我 运行 node server.js 时的错误 - 后者仅用于上下文。

正如@jonrsharpe 在评论中指出的那样,我假设使用 module.exports 我导出了应用程序本身,但实际上我导出了一个包含该应用程序的对象。因此,为了修复测试错误,我不得不简单地写在我的 test.js:

server = require('../app').app;

而不是 server = require('../app');。同样,在 server.js 中我不得不写:

const app = require('./app').app;

这修复了我在问题中提到的两个错误 (TypeError: app.address is not a function)。

感谢@jonrsharpe 帮助我找到解决方案!