繁体   English   中英

测试快速 HTTPS 服务器时的“app.address 不是函数”

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

我在测试我的快速应用程序时遇到了问题。 所有教程都使用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”。 Webstorm IDE。

尝试了以下各种组合:

  • 将应用程序和服务器合并到一个文件中(见下文)
  • 在单独的 function 中创建服务器并将其导出
  • 使用 mocha/chai 代替 jest
  • 测试应用程序的精简版本

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

  • 类型错误:app.address 不是 function
  • 类型错误:app.get 不是 function
  • EADDRINUSE: 地址已经在使用::::443
  • 其他各种超时错误,错误的 arguments 等。

没有帮助的相关主题(或者我忽略了一些东西):

语境

我在上面包含了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我导出了应用程序本身,但实际上我导出了一个包含该应用程序的 object。 因此,要修复测试错误,我必须简单地在test.js中编写:

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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