I'm using Restify for my API and I'm trying to write tests for my endpoints.
At first, I had only a test for ping
and it was okay, but now, after I added a new test, supertest
is trying to ephemeral ports to the test server (80201).
I've searched a lot and tried some approaches that seem to work for most people but not for me. I'm probably messing something up, but I have no clue what it could be.
Check out my code:
server.js
require('dotenv').config();
const config = require('./config');
const routes = require('./src/routes');
const cors = require('restify-cors-middleware');
const http = require('http');
const https = require('https');
const restify = require('restify');
module.exports = function () {
http.globalAgent.keepAlive = true;
http.globalAgent.maxSockets = 256;
https.globalAgent.keepAlive = true;
https.globalAgent.maxSockets = 256;
const _cors = cors({
preflightMaxAge: 5,
origins: [new RegExp("^(https?:\/\/)?[-\w]+\.hackz\.co(\.\w+)?(:[\d]+)?$")],
allowHeaders: [
'authorization',
'x-requested-with',
'Content-MD5',
'Date',
'Accept-Version',
'Api-Version',
'Response-Time'
],
credentials: true
});
const server = restify.createServer({ name: config.apiName });
// Middlewares
server.pre(_cors.preflight);
server.use(_cors.actual);
server.use(restify.plugins.fullResponse());
server.use(restify.plugins.queryParser({ mapParams: true }));
server.use(restify.plugins.bodyParser({ mapParams: true }));
// Load Routes
routes.set(server);
server.on('error', function (req, res, route, error) {
if (error && (error.statusCode == null || error.statusCode !== 404)) {}
});
// Start Server
server.listen(config.apiPort, function () {
console.log(`${server.name} listening at ${server.url}.\nWe're in ${config.env} environment!`);
});
return server;
}();
tests/config/server.js
const server = require('../..');
const request = require('supertest');
function TestServer() {
return request(server);
}
module.exports = { TestServer };
tests/services/request.js
const { TestServer } = require("../config/server");
async function get(path, sessionkey = '', params = {}) {
const server = TestServer();
return await server
.get(path)
.query(params)
.set("authorization", sessionkey)
.set("content-type", "application/json")
;
}
async function post(path) {
const server = TestServer();
return await server
.post(path)
.set("content-type", "application/json")
;
}
module.exports = {
get,
post,
};
tests/config/setup.js
const server = require('../..');
afterAll(() => {
return server.close()
});
src/controllers/Ping.test.js
const { get } = require('../../tests/services/request');
describe('Ping Controller', () => {
describe('GET /ping', () => {
it('Should return 200', async () => {
const response = await get('/ping');
expect(response.status).toBe(200);
});
});
});
src/controllers/Session.test.js
const { post } = require('../../tests/services/request');
describe('Session Controller', () => {
const userId = 1;
describe('POST /:userId/create', () => {
it('Should create session successfully!', async () => {
const response = await post(`${userId}/create`);
expect(response.status).toBe(200);
expect(response.body.auth).toBe(true);
});
});
});
package.json (scripts and Jest config)
...
"scripts": {
"start": "node index.js",
"test": "jest --detectOpenHandles --forceExit --coverage",
"test:api": "npm run test -- --roots ./src/controllers"
},
...
"jest": {
"setupFilesAfterEnv": [
"jest-extended",
"<rootDir>/tests/config/setup.js"
],
...
}
This is the error output:
> [email protected] test
> jest --detectOpenHandles --forceExit --coverage
FAIL src/controllers/Session.test.js
Session Controller
POST /:userId/create
✕ Should create session successfully! (39 ms)
● Session Controller › POST /:userId/create › Should create session successfully!
RangeError: Port should be >= 0 and < 65536. Received 80201.RangeError [ERR_SOCKET_BAD_PORT]: Port should be >= 0 and < 65536. Received 80201.
Things I've tried:
- Passing the result of
server.listen(...)
(instead of the server instance) tosupertest
(as described here); - Using
beforeEach
for each test manually listening to a specific port; - This approach, which is similar to the first item.
HELP!
UPDATE:
Just realized that running npm run test "Ping.test.js"
it succeeds and running npm run test "Session.test.js"
(which is the new test) it fails. So there's probably something wrong with that single file.