0

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

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

我已经读过这个- 解释可能仍然有一些异步进程打开,例如打开的套接字,但我尝试终止套接字,并且我得到了“关闭”事件触发(我得到了我定义的控制台日志消息'close' 事件监听器),但测试仍未结束。

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

版本:

"ws": "^7.3.0",

"摩卡": "^7.0.0",

"柴": "^4.2.0",

"超测"​​: "^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?

4

1 回答 1

0

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

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

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

它发现我有另一个具有相同基本结构的测试 - 在“描述”部分我有:

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 会运行所有测试中的所有描述,如果其中一个上有“only”标志

由于运行了另一个测试的“describe”部分,还有另一个打开的 websocket,所以测试卡住了。

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

于 2020-06-11T08:26:05.807 回答