Jest + Supertest - API 测试使用随机临时端口

时间:2021-04-28 14:28:27

标签: node.js jestjs supertest restify

我正在为我的 API 使用 Restify,并且我正在尝试为我的端点编写测试。 起初,我只对 ping 进行了测试,还可以,但是现在,在我添加新测试后,supertest 尝试将临时端口连接到测试服务器 (80201)。

我进行了大量搜索并尝试了一些似乎对大多数人有效但对我无效的方法。我可能搞砸了一些事情,但我不知道它可能是什么。

查看我的代码:

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

测试/服务/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(脚本和 Jest 配置)

...

"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"
    ],
    ...
}

这是错误输出:

> user-session-api@1.0.0 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.

我尝试过的事情:

  • server.listen(...) 的结果(而不是服务器实例)传递给 supertest(如 here 所述);
  • 对每个测试使用 beforeEach 手动侦听特定端口;
  • This approach,类似于第一项。

帮助!

更新: 刚刚意识到运行 npm run test "Ping.test.js" 成功,运行 npm run test "Session.test.js" (这是新测试)失败。所以这个文件可能有问题。

1 个答案:

答案 0 :(得分:0)

天啊!

我发现了这个问题,并做好准备,解决方案很荒谬。

我测试中的请求路径有误。

我是这样做的:

const response = await post(`${userId}/create`); // with userId as 1

路径缺少首字母 /,就是这样,哈哈。

这就是 supertest1 附加到服务器端口并引发 RangeError 的原因。

我现在很讨厌自己。