I am running into issues when testing my express application. All tutorials use app.listen
instead of https.createServer
and I don't know how to properly use testing frameworks with the latter. The code:
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"
}
}
The error I get when I test the above code with 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
This is obviously a stripped down version of my code. I also create MongoDB connections at start, but I removed them for simplicity. Ideally I want to use async/await instead of promises for creating my server (and MongoDB connections) before my tests start. I also need to close those connections after tests end or fail. In your answer you can safely assume I'm JS beginner :).
Additional info
I'm using node '14.15.4' on Windows 10 x64. Webstorm IDE.
Tried various combinations of the following:
- combining app and server in one file (see below)
- creating the server in a separate function and exporting it
- using mocha/chai instead of jest
- testing a stripped down version of the app
Errors I get depending on the combinations I tried:
- TypeError: app.address is not a function
- TypeError: app.get is not a function
- EADDRINUSE: address already in use ::::443
- various other errors with timeouts, wrong arguments, etc.
Relevant topics that didn't help (or I overlooked something):
- Simple node http server unit test
- Is it possible to create an Express.js server in my Jest test suite?
- TypeError: app.get is not a function
- Mocha API Testing: getting 'TypeError: app.address is not a function'
- Getting "TypeError: "listener" argument must be a function" in Node.Js
- Jest/Supertest errors with TypeError: app.address is not a function
- https://blog.campvanilla.com/jest-expressjs-and-the-eaddrinuse-error-bac39356c33a
- https://glebbahmutov.com/blog/how-to-correctly-unit-test-express-server/
- https://rahmanfadhil.com/test-express-with-supertest/
- https://zellwk.com/blog/endpoint-testing/
- https://taylor.fausak.me/2013/02/17/testing-a-node-js-http-server-with-mocha/
- https://www.albertgao.xyz/2017/05/24/how-to-test-expressjs-with-jest-and-supertest/
Context
I included the server.js
file above, although the test doesn't use it, because my server application should also be able to start normally when I run node server.js
. With the above code it doesn't start and I get the following error:
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'
}
However, if I put all code in the same app.js
file and I run node app.js
, then the app starts fine, although the test produces the same error.
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
}
To clarify, my question is how to fix the error from the jest test and not about the error when I run node server.js
- the latter is just for context.