2014-01-22 134 views
6

我使用標準配置的sockjs。如何測試node.js websocket服務器?

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 
} 

稱爲在開關每個方法發送回一個消息給客戶端。

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測試,但我只是不知道如何處理websocket。

我想通過所有測試只有一個websocket連接重用,我在第一條消息後綁定websocket連接和用戶會話,我也想測試持久性。

如何使用ws客戶端的onmessage事件並在我的測試中使用它?測試如何分辨收到的消息並知道他們應該等待哪一個?

回答

1

Collegue在工作中詢問它是否真的需要成爲客戶端連接或者是否可以將其模擬出來。事實證明,這是要走的路。我寫了一個小的輔助類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); 
     } 
    } 
} 

現在在我的摩卡測試我只是做

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

它的工作原理就像一個魅力,堅持請求之間的連接狀態和變量。