使用 websockets 时 mocha 测试不退出,即使使用 websocket。close/termintae

mocha test not exiting when using websockets, even with websocket.close/termintae

我正在尝试测试我的 websocket 服务器,方法是在我的 mocha 测试文件中打开一个 websocket 客户端,连接到 ws 服务器并等待响应。我向ws服务器发送一个http请求,然后通过websocket向客户端发送一条消息,我在客户端存储结果并进行测试。

我得到了我想要的响应并且测试通过了,但是 mocha 测试本身并没有终止,我不得不手动关闭它。

我已阅读 this - 解释说可能仍有一些异步进程处于打开状态,例如打开的套接字,但我尝试终止套接字,并收到 'close' 事件fire(我收到了我在 'close' 事件侦听器中定义的控制台日志消息),但测试仍未结束。

我正在使用 ws (npm)、mocha、chai(用于断言)和 supertest(调用服务器发送响应)。

版本:

"ws": "^7.3.0",

"mocha": "^7.0.0",

"chai": "^4.2.0",

"supertest": "^4.0.2",

节点:v12.9.1

我知道我可以使用 --exit 标志,正如 中所建议的那样,但如果可以避免的话,我不想这样做。

相关代码如下:

'use strict';
const supertest = require('supertest');
const assert = require('chai').assert;
const paths = require('../common/paths');
const { sign } = require('../common/signing');
const WebSocket = require('ws');

describe.only('Events server tests', function () {
    this.timeout(11000);

    const docId = 'doc_events_' + Date.now();
    const wsServerUrl = 'ws://localhost:8080/subscribe?params={"prefix_doc_id":"doc_events_"}';
    const ws = new WebSocket(wsServerUrl);
    let id_from_msg;
    // Connection opened
    ws.addEventListener('open', function (event) {
        console.log('connection started!');
    });
    // Listen for messages
    ws.addEventListener('message', function (event) {
        console.log('\n\nMessage from server ', event.data, ' ', typeof event.data);
        try {
            // the msg recived via websocket is in the form of: "doc_id":X, and I store the docID in order to check if it matches the docId that was sent in the test.
            if (event.data.includes('doc_id')) {
                id_from_msg = JSON.parse(event.data).doc_id;
            }
        } catch (error) {
            console.log('error: ', error);
        }
    });
    ws.addEventListener('close', () => {
         console.log('closed connection!');
    });

    before((done) => {
        console.log('start');
        done();
    });

    after((done) => {

        ws.terminate();
        // ws.close();
        done();
        console.log('after?');
    });

    it('Test 1 - send simple request to events server', (done) => {
        const eventsUrl = paths.EVENTS.EVENTS();
        const eventsObj = {
            reqId: '',
            docId: docId,
            sessionId: 1,
            status: 200
        };
        // This tests is used to invoke response from the socket server, and it works fine, the tests passes and ends without an issue.
        supertest('http://localhost:3035')
            .post(eventsUrl)
            .set('Authorization', sign('post', eventsUrl, eventsObj))
            .send(eventsObj)
            .expect(200)
            .expect(res => {
                assert.ok(res.body);
                assert.equal(id_from_msg, docId);
            })
            .end(done);
    });

});

如您所见,我在 "after" 部分尝试了 ws.close() 和 ws.terminate(),两者都产生了相同的结果:测试没有结束, console.log('after?') 行在 done() 被调用后触发。

我试图覆盖 'onclose' 方法并手动触发,但无济于事。

我也尝试在测试本身中关闭 websocket(我的意思是在 'it' 部分,即使我在语义上不喜欢它) - 但测试套装本身不会终止,与之前。

有没有办法确保在之后调用 done() 之前正确关闭 websocket?

我找到了一个解决方案,因为它很奇怪,所以我 post 在这里,所以如果有人遇到类似的事情 he/she 可以寻求帮助:

问题的核心是当测试应该结束时一些异步进程仍然打开,但似乎在这个测试中所有的 websockets 都关闭了。

但这是奇怪的部分 - 在这个测试中,所有的 ws 都是关闭的,在其他测试中它不是。

它发现我有另一个具有相同基本结构的测试 - 在 "describe" 部分我有:

const docId = 'doc_events_' + Date.now();
const wsServerUrl = 'ws://localhost:8080/subscribe?params={"prefix_doc_id":"doc_events_"}';
const ws = new WebSocket(wsServerUrl);

即使我在测试中有“.only”,我也想 运行,似乎 mocha 运行s 都描述了所有测试,事件如果有是其中之一的 "only" 标志

由于另一个测试的"describe"段是运行,又打开了一个websocket,所以测试就卡住了。

这是一个非常奇怪的行为,也许我以后会就此联系 mocha 团队,但现在 - 我希望这能有所帮助。