【问题标题】:Killing a node.js server (launched in jest's setup hook) in jest teardown在 jest 拆解中杀死 node.js 服务器(在 jest 的 setup 挂钩中启动)
【发布时间】:2019-03-21 18:50:31
【问题描述】:

我使用Jest 作为测试库,在它的setup hook(在我的所有测试之前执行)内部,我spawn 是一个子进程,它在某个端口上启动测试服务器。 设置代码基本上执行一个 NPM 命令:

"run-server-test": "NODE_ENV=test SERVER_PORT=3001 node src/index.js &",
"test": "NODE_ENV=test SERVER_PORT=3001 jest --detectOpenHandles --forceExit",

这是设置函数:

const { spawn } = require("child_process")

module.exports = async function setup() {
  return new Promise((resolve, reject) => {
    const testServerProcess = spawn("npm", ["run", "run-server-test"])

    testServerProcess.on("error", err => {
      console.log("Failed to start subprocess.", err)
      reject(err)
    })

    testServerProcess.stdout.on("data", data => {
      if (data.toString().startsWith("Apollo Server")) {
        console.log(`\nTest server running with PID ${testServerProcess.pid}`)
        resolve(true)
      }
    })

    testServerProcess.stderr.on("data", data => {
      console.error(`stderr: ${data}`)
      reject(new Error(data.toString()))
    })
  })
}

请注意,我使用& 在后台执行命令。当 Jest 完成它的工作时,我注意到 ps 它的 PID 与 shell 中显示的不同。如果不在后台执行它,我会得到一个额外的进程,即 shell 的进程 (/bin/sh)。 我怎样才能获得该进程的真实 PID? 有没有最好的方法来终止该函数内启动的进程? 谢谢!

【问题讨论】:

    标签: node.js child-process


    【解决方案1】:

    我目前的做法如下:

    • 将 Express 引导过程包装在一个函数中,该函数返回用于使服务器侦听请求的 httpServer 实例。这是 beforeAll 钩子的好例子。
    • 使用前面的引用关闭afterAll中的服务器。

    另一种选择(有点棘手),可能是在所有测试开始时启动服务器一次并在结束时关闭它:

    • 直接产生节点进程而不是通过npm
    • 将进程 ID 存储在临时 mongo 的集合中(但可以是任何东西)
    • 在拆解中,我检索了 PID,然后我就执行process.kill(PID, "SIGTERM")

    【讨论】:

      【解决方案2】:

      您可以在服务器上创建启动和停止方法。这样您就不必担心分叉您的进程。

      我以快递为例。

      app.js

      const start = async (callback => { 
        await database.connect();
        server.listen(config.port, config.ip, () => {
          callback();
        });
      };
      
      const stop = (callback => {
        server.close(async () => {
          await database.disconnect();
          callback();
        });
      };
      

      app.test.js

      const server = require('./path/to/server');
      
      beforeAll(async () => {
        try {
          await server.start();
        } catch (error) {
          // if the server doesn't start up or the seeding fails, just
          // exit the process ASAP
          process.exit(1);  
        }
      });
      
      afterAll(done => {
        server.stop(done);
      });
      

      【讨论】:

        猜你喜欢
        • 2020-03-19
        • 2020-10-15
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        • 2020-06-01
        • 2014-03-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多