【问题标题】:Async testing a TCP server with Node net - Why are my tests throwing 'Cannot log after tests are done'?使用 Node net 异步测试 TCP 服务器 - 为什么我的测试会抛出“测试完成后无法记录”?
【发布时间】:2021-07-09 16:55:03
【问题描述】:

上下文

我已经启动了一个 TCP Echo 服务器,并正在尝试为其编写集成测试。我熟悉测试,但不熟悉异步。

期望的行为

我希望我的测试能够监视日志以验证代码是否正在执行。任何异步代码都应该被正确处理,但这就是我的理解失败的地方。

问题

我收到异步错误:

Cannot log after tests are done. Did you forget to wait for something async in your test? Attempted to log "Server Ready". Attempted to log "Client Connected".

最后是一个警告:

A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks.

代码

import * as net from 'net';
export const runServer = async () => {
  console.log('Initialising...');
  const port: number = 4567;
  const server = net.createServer((socket: net.Socket) => {
    socket.write('Ready for input:\n');
    console.log('Client Connected');
    socket.on('data', (data) => {
      echo(data, socket);
      server.close();
    })
    socket.on('end', () => {
      console.log('Client Disconnected');
    });
  });
  server.listen(port, () => {
    console.log('Server Ready');
  });
  server.on('error', (err) => {
    console.log(err);
  });
  function echo(data: Buffer, socket: net.Socket) {
    console.log('Input received')
    socket.write(data)
  };
  return server;
}

测试

当这些测试按预期工作时,将添加更多此类测试。

import * as index from '../../src/index';
import * as process from 'child_process';
test('the server accepts a connection', async () => {
  const consoleSpy = spyOn(console, 'log');
  try {
    const server = await index.runServer();
    await consoleConnect();
    await consoleEcho();
    await consoleStop();
  } catch (error) {
   console.log(error);
  }
  expect(consoleSpy).toHaveBeenCalledWith('Initialising...');
  expect(consoleSpy).toHaveBeenCalledWith('Client Connected');
  expect(consoleSpy).toHaveBeenCalledTimes(2);
})
const consoleConnect = async () => {
  process.exec("netcat localhost 4567");
}
const consoleEcho = async () => {
  process.exec("Echo!");
}
const consoleStop = async () => {
  process.exec("\^C");
}

我的总体问题是如何管理事件以使测试能够在没有异步相关错误的情况下运行?

【问题讨论】:

    标签: node.js typescript asynchronous async-await jestjs


    【解决方案1】:

    您没有正确等待子进程完成。对 exec 的调用会返回一个 ChildProcess 对象,如文档中的 here 所示。它们是异步执行的,因此您需要等待它们完成使用事件发射器 api。

    文档中的示例

    ls.on('exit', (code) => {
      console.log(`child process exited with code ${code}`);
    });
    

    要使用异步等待,您需要转换为使用承诺。类似的东西

    return new Promise((resolve, reject) => {
        ls.on('exit', (code) => {
          resolve(code);
        });
        // Handle errors or ignore them. Whatevs.
    }
    

    您将在第一个数据事件时关闭您的服务器。你可能不想这样做。至少等到结束事件,这样你就已经读取了所有数据。

    socket.on('data', (data) => {
          echo(data, socket);
          server.close(); // Remove this line
        })
    

    【讨论】:

    • 这很好,我已经删除了该行,但我得到了相同的关键错误。
    猜你喜欢
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    相关资源
    最近更新 更多