How to test node.js websocket server?

I am using sockjs with a standard configuration.

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); 
Function

wsParser.parse works as follows:

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

Each method called on the switch sends a message back to the client.

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

Now my problem is that I would like to do tests for my code (better late than I guess), and I have no idea how to do this. I started writing regular http tests using mocha + supertest, but I just don't know how to handle websockets.

I would like to have only one network connection to reuse all tests, I bind the websocket connection to the user session after the first message, and I want to check this persistence as well.

How can I use the ws client onmessage event and use it in my tests? How can tests tell you about all messages received and find out which one they should wait for?

+6
source share
1 answer

Collegue at work asked if it really should be a client connection or just mock it. It turned out that this was the way to go. I wrote a small helper class 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); } } } 

Now in my mocha test I'm just doing

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

It works like a charm and saves connection status and variables between requests.

+1
source

All Articles