如果给出服务器的响应,如何测试失败?

时间:2016-07-25 17:32:40

标签: javascript node.js socket.io mocha

我正在使用socket.io IRC,我不希望用户拥有长用户名。我编写了以下(mocha)测试来验证当提供更长的用户名时服务器不会向每个连接的套接字发送响应:

  it("should not accept usernames longer than 15 chars", function (done) {
    var username = "a".repeat(server.getMaxUsernameLength() + 1);
    client1.emit("username change", username);
    client2.on("chat message", function (data) {
      throw Error("Fail, server did send a response.");
    });
    setTimeout(function () {
      done();
    }, 50);
  });

这目前确实有效,但远非最佳。如果我的CI平台速度较慢或服务器在超过50毫秒后响应怎么办?在给出响应时,测试失败的最佳方法是什么,或者我应该以不同方式构建测试?

谢谢!

P.S。这个问题与Testing asynchronous function with mocha不同,因为虽然问题确实与异步测试有关,但我知道done()方法(我明显使用它)。

1 个答案:

答案 0 :(得分:0)

您要做的是验证永远不会调用client2.on("chat message"...的回调。对负面案例进行测试可能很困难,而且您尝试进行完整的端到端(客户端到服务器到客户端)集成测试这一事实似乎加剧了您的情况。就个人而言,我会尝试在单元案例套件中对此进行测试,并避免在测试中引入异步性的复杂性。

但是,如果必须这样做,请参考Eradicating Non-Determinism in Tests提示:

  

这是最棘手的情况,因为您可以测试您的预期响应,但除了超时之外没有任何事情可以检测故障。如果提供者是你正在构建的东西,你可以通过确保提供者实现某种方式来表明它已经完成 - 基本上是某种形式的回调来处理这个问题。即使只有测试代码使用它,它也是值得的 - 尽管通常你会发现这种功能对其他目的也有价值。

您的服务器应该向client1发送某种通知,即使您没有进行测试,它也会忽略名称更改,但是因为您可以使用此类通知来验证它确实没有不向其他客户发送通知。如下所示:

it("should not accept usernames longer than 15 chars", function (done) {
  var chatSpy = sinon.spy();
  client2.on("chat message", chatSpy);
  client1.on('error', function(err) {
    assertEquals(err.msg, 'Username too long');
    assert(chatSpy.neverCalledWith(...));
    done();
  });

  var username = "a".repeat(server.getMaxUsernameLength() + 1);
  client1.emit("username change", username);
});

适合。

此外,如果由于某种原因server.getMaxUsernameLength()开始返回15以外的其他内容,最好的情况是您的测试说明出错了。如果getMaxUsernameLength并且用于处理名称更改事件的服务器代码未从同一位置获取其值,则可能会变得更糟。测试可能不应该依赖于被测系统来提供测试值。