如何在 mocha 超时时关闭侦听 UDP 套接字?

How to close listening UDP sockets when mocha times-out?

我有一些绑定到 UDP 端口的测试,例如

describe('the server', function() {
  it('should respond to a udp packet', function(done) {
    const udp = dgram.createSocket('udp4');

    udp.on('error', function(error) {
      console.log(error);
    });

    udp.on('message', function(msg, rinfo) {
      console.log('msg', msg);
      console.log('rinfo', rinfo);
      // TODO: check the reply
      udp.close();
      done();
    });
    udp.bind();

    // send a request
    const bytes = Buffer.from("421a0800117860bc457f0100001a0653455256455222054d54303031", 'hex');
    udp.send(bytes, SERVER_PORT, SERVER_ADDR)
  });
});

测试成功完成后,该代码路径可以调用 udp.close() 让 mocha 退出。

当测试超过 mocha 的 2 秒超时时,我看到错误但 mocha 没有退出,因为 UDP 端口仍在侦听。

当 mocha 的 2 秒超时触发时,是否有某种形式的 callback/event 可以用来关闭侦听的 UDP 套接字?

这可以通过 afterEach 挂钩来实现。 afterEach 挂钩是在每次测试后执行的函数,无论是通过还是失败(但未跳过)。因此执行清理操作很有用,例如在这种情况下关闭套接字。

与所有 Mocha hooks 一样,afterEach 是在 describe 函数调用中定义的,它适用于该范围内的所有测试。如果您只想在一个特定测试后挂钩 运行,请将该测试放入专用的 describe 函数中。

所以这里要做的更改如下:

  • udp 的声明从 it 函数移动到包含 describe 的函数中。这将使 udp 可以从 itafterEach.
  • 访问
  • 添加一个 afterEach 挂钩来执行清理操作:udp.close();。请记住,这将 运行 无论测试因任何原因通过还是失败,因此最好避免对测试进度做出假设。这里:不要假设已经创建了 udp
  • 删除对 udp.close(); 的其他调用,现在不再需要这些。
describe('the server', function() {
  let udp;

  afterEach(() => {
    if (udp) {
      udp.close();
      udp = undefined;
    }
  });

  it('should respond to a udp packet', function(done) {
    udp = dgram.createSocket('udp4');

    udp.on('error', function(error) {
      console.log(error);
    });

    udp.on('message', function(msg, rinfo) {
      console.log('msg', msg);
      console.log('rinfo', rinfo);
      // TODO: check the reply
      done();
    });
    udp.bind();

    // send a request
    const bytes = Buffer.from("421a0800117860bc457f0100001a0653455256455222054d54303031", 'hex');
    udp.send(bytes, SERVER_PORT, SERVER_ADDR)
  });
});

需要注意的是,在超时的情况下,测试函数可能会在套接字关闭后保持 运行ning,产生各种莫名其妙的错误消息:这并不奇怪。

另一个需要注意的有趣的事情是 describe 函数调用中的变量(不同于 it 函数调用中的变量)与 Mocha 运行 具有相同的生命周期。出于这个原因,通常的做法是在需要时(在测试中)延迟创建这些变量,并在不再需要时通过将它们显式设置为 undefinednull 来手动清除。

您也可以使用mocha --exit,这比您自己关闭套接字要简单得多。