node.js - 如何测试 node.js websocket 服务器?

标签 node.js unit-testing websocket mocha.js sockjs

我正在使用标准配置的 sockjs。

   var ws = sockjs.createServer();
    ws.on('connection', function(conn) {
        conn.on('data', function(message) {
            wsParser.parse(conn, message)
        });
        conn.on('close', function() {

        });
    });

    var server = http.createServer(app);
    ws.installHandlers(server, {prefix:'/ws'});
    server.listen(config.server.port, config.server.host);

wsParser.parse 函数的工作原理如下:

function(conn, message) {

(...)

switch(message.action) {
    case "titleAutocomplete":
        titleAutocomplete(conn, message.data);
        break;
    (...) // a lot more of these
 }

在 switch 中调用的每个方法都会向客户端发送回一条消息。

var titleAutocomplete = function(conn, data) {

    redis.hgetall("titles:"+data.query, function(err, titles){
        if(err) ERR(err);

        if(titles) {
            var response = JSON.stringify({"action": "titleAutocomplete", "data": {"titles": titles}});
            conn.write(response);
        } 
    })
};

现在我的问题是我想对我的代码进行测试(我想迟到总比不测试好),但我不知道该怎么做。我开始使用 mocha + supertest 编写普通的 http 测试,但我只是不知道如何处理 websockets。

我希望只有一个 websocket 连接可以在所有测试中重用,我在第一条消息后将 websocket 连接与用户 session 绑定(bind),我也想测试这种持久性。

我如何利用 ws 客户端的 onmessage 事件并在我的测试中使用它?测试如何区分收到的消息并知道它们应该等待哪一条消息?

最佳答案

工作中的同事问它是否真的需要一个客户端连接,或者是否可以模拟它。事实证明这是要走的路。我写了一个小助手类 wsMockjs

var wsParser = require("../wsParser.js");

exports.createConnectionMock = function(id) {
    return {
        id: id,
        cb: null,
        write: function(message) {
            this.cb(message);
        },
        send: function(action, data, cb) {
            this.cb = cb;
            var obj = {
                action: action,
                data: data
            }
            var message = JSON.stringify(obj);
            wsParser.parse(this, message);
        },
        sendRaw: function(message, cb) {
            this.cb = cb;
            wsParser.parse(this, message);
        }
    }
}

现在在我的 mocha 测试中,我只是这样做

var wsMock = require("./wsMock.js");
ws = wsMock.createConnectionMock("12345-67890-abcde-fghi-jklmn-opqrs-tuvwxyz");
(...)
describe('Websocket server', function () {

    it('should set sessionId variable after handshake', function (done) {
        ws.send('handshake', {token: data.token}, function (res) {
            var msg = JSON.parse(res);
            msg.action.should.equal('handshake');
            msg.data.should.be.empty;
            ws.should.have.property('sessionId');
            ws.should.not.have.property('session');
            done();
        })
    })

    it('should not return error when making request after handshake', function (done) {
        ws.send('titleAutocomplete', {query: "ter"}, function (res) {
            var msg = JSON.parse(res);
            msg.action.should.equal('titleAutocomplete');
            msg.data.should.be.an.Object;
            ws.should.have.property('session');
            done();
        })
    })
})

它就像一个魅力,在请求之间保持连接状态和变量。

关于node.js - 如何测试 node.js websocket 服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21293311/

相关文章:

unit-testing - 声明在 Controller 中设置的 session 变量-Grails测试用例

c# - 如何轻松替换 Microsoft Fakes 程序集?

ios - IOS 上的 Safari 中每个域允许多少个同时 websocket 连接?

ruby-on-rails - 在开发环境中使用 SSL/TLS 的 Rails 和 WebSockets

JavaScript Promises - 创建一组要一起执行的 promise

javascript - 被另一个元素 Cypress 覆盖

javascript - 简单的 node.js 服务器返回成功或错误

Javascript 深复制 Squel 对象

c# - 单元测试 AAA 模式中的数据提取

c# - 如何使用 SuperWebSocket 创建 WebSocket 服务器