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

How to fail test if response from server is given?

本文关键字:失败 测试 何失败 服务器 响应 如果      更新时间:2023-09-26

我正在开发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毫秒后做出响应,该怎么办?当给出响应时,测试失败的最佳方式是什么?或者我应该以不同的方式构建测试?

谢谢!

附言:这个问题与用mocha测试异步函数不同,因为虽然这个问题确实与异步测试有关,但我知道done()方法(我显然正在使用它)。

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

然而,如果必须这样做的话,这里有一个来自消除测试中的非决定性因素的提示:

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

您的服务器应该向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和用于处理名称更改事件的服务器代码没有从同一位置获取它们的值,情况可能会变得更糟。测试可能不应该依赖于被测系统来提供测试值。