dimanche 7 juin 2020

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

I'm trying to test my websocket server, by opening a websocket client in my mocha test file, connection to the ws server and awaiting response. I send an http request to the ws server, and then a message is sent via websocket to the client, where I store the results and test it.

I get the response I want and the test passes, but the mocha test itself does not terminate and I'm forced to close it manually.

I have read this - explaining that there is probably still some async process open, such as an open socket, but I try to terminate the socket, and I get the 'close' event to fire (I get the console log message I defined in the 'close' event listener), but the test still isn't over.

I'm using ws (npm), mocha, chai (for asserts) and supertest (to invoke the server to send a response).

versions:

"ws": "^7.3.0",

"mocha": "^7.0.0",

"chai": "^4.2.0",

"supertest": "^4.0.2",

node: v12.9.1

I know I can use the --exit flag, as is suggested in this stack overflow answer, but I prefer not to, if it can be avoided.

Here is the relevant code:

'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 {
            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);
    });

});

As you can see, I tried both ws.close() and ws.terminate() inside the "after" section, and both yield the same result: the test does not end, and the console.log('after?') line is fired after done() is called.

I tried to overwrite 'onclose' method and to fire in manually, but to no avail.

I tried also to close the websocket in the test itself (I mean in the 'it' section, even though I don't like it semantically) - but the test suit itself does not terminate, same as before.

Is there a way to make sure that the websocket is properly closed before done() is called in after?

Aucun commentaire:

Enregistrer un commentaire