【问题标题】:Testing client connection on the server side with websockets in mocha在 mocha 中使用 websockets 在服务器端测试客户端连接
【发布时间】:2018-04-01 22:24:49
【问题描述】:

我使用 socket.io 库制作了一个简单的示例应用程序,现在我想测试我的 io.on("connection") 在客户端连接时是否被调用。

所以我在我的单元测试中创建了一个简单的假客户端,它成功连接到服务器,但是监视由io.on("connection") 触发的方法handleSocket 的间谍说它从未被触发过,这显然是根据日志。

这可能是我无法弄清楚的时间/异步问题。

服务器端代码:

const express = require("express");
const app = express();
const port = process.env["PORT"] || 3030;
var io = require("socket.io").listen(port);
io.on("connect", socket => handleSocket(socket));
function handleSocket(socket) {
  console.log("a user connected", socket.id);
}
exports.io = io;
exports.handleSocket = handleSocket;

mocha 中的实际单元测试:

var expect = require("chai").expect;
var sinon = require("sinon");
var ioClient = require("socket.io-client");
process.env["PORT"] = 3030;
process.env["VERBOSE"] = true;
var options = {
  transports: ["websocket"],
  "force new connection": false
};
describe("server.spec", function() {
  this.timeout(5000);
  it("Client should connect", function(done) {
    app = require("./server2");
    let spy = sinon.spy(app.handleSocket);
    var client = ioClient.connect("http://localhost:" + process.env["PORT"], options);
    client.on("connect", function() {
      expect(spy.called).to.be.equal(true);
      client.disconnect();
      app.io.close();
      done();
    });
  });
});

测试 - 失败,spy.call 等于 false 日志输出:

  server.spec
a user connected jopFRhcfzjkC_TjsAAAA
Spy was called: false
    1) Client should connect
a user connected uIpW2gsiljJkS4wFAAAB
Spy was called: false

【问题讨论】:

    标签: node.js unit-testing socket.io mocha.js


    【解决方案1】:

    我认为这里的文档:http://sinonjs.org/releases/v4.5.0/spies/,关于创建间谍的部分对于这个用例有点不清楚:

    var spy = sinon.spy(myFunc);
    

    如果您以这种方式创建间谍,则意味着 spy 是您需要调用的函数。即,它围绕 myFunc 创建一个代理,但如果您直接调用 myFunc,它实际上并不使用该代理。您需要的是:var spy = sinon.spy(object, "method");,所以您的示例将变为:

    服务器代码:

    const express = require("express");
    const app = express();
    const port = process.env["PORT"] || 3030;
    var io = require("socket.io").listen(port);
    
    exports.handleSocket = function(socket) {
      console.log("a user connected", socket.id);
    };
    
    // NOTE: we use handleSocket as method of exports here
    io.on("connect", socket => exports.handleSocket(socket));
    
    exports.io = io;
    

    测试规范:

    var expect = require("chai").expect;
    var sinon = require("sinon");
    var ioClient = require("socket.io-client");
    process.env["PORT"] = 3030;
    process.env["VERBOSE"] = true;
    var options = {
      transports: ["websocket"],
      "force new connection": false
    };
    describe("server.spec", function() {
      this.timeout(5000);
      it("Client should connect", function(done) {
        app = require("./server2");
        let spy = sinon.spy(app, "handleSocket"); // <- CHANGED CODE
        var client = ioClient.connect("http://localhost:" + process.env["PORT"], options);
        client.on("connect", function() {
          expect(spy.called).to.be.equal(true);
          client.disconnect();
          app.io.close();
          done();
        });
      });
    });
    

    当您以这种方式创建间谍时,它实际上会替换对象 (app) 上的方法 (handleSocket),该对象与从服务器代码中导出的对象相同。

    【讨论】:

    • 这确实有效,干杯!您是否介意再解释一下,这如何使事件调用正确的(由间谍包装的)方法?
    • 当您调用 sinon.spy(app,"handleSocket") 时,您将 app.handleSocket 替换为一个新函数(间谍),该函数将在调用时调用原始函数,但具有您期望的间谍的额外功能(跟踪调用次数、参数等)。由于您的测试规范中的app 对象与您的服务器代码中导出的对象完全相同,因此您也有效地将服务器代码中的exports.handleSockets 函数替换为同一个间谍。 exports.handleSockets 用作事件处理程序。让我知道这是否可以澄清。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 2013-05-18
    • 1970-01-01
    • 2015-09-21
    相关资源
    最近更新 更多