在 jest 拆解中杀死 node.js 服务器(在 jest 的设置挂钩中启动)
Killing a node.js server (launched in jest's setup hook) in jest teardown
我正在使用 Jest as a testing library and inside its setup hook (which is executed before all my tests), I 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?
有没有最好的方法来终止在该函数内启动的进程?
谢谢!
您可以在服务器上创建启动和停止方法。这样你就不用担心分叉你的进程了。
我以快递为例。
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);
});
我目前的做法如下:
- 将 Express bootstrap 进程包装在一个函数中,returns
httpServer
实例用于使服务器侦听请求。这是 beforeAll
钩子的一个很好的例子。
- 在
afterAll
. 中使用之前的参考关闭服务器
另一种选择(有点棘手)可能是在所有测试开始时启动服务器一次并在结束时关闭它:
- 直接生成节点进程而不是通过
npm
- 将进程 ID 存储在临时 mongo 的集合中(但可以是任何东西)
- 在拆解中,我检索了 PID,然后我就做
process.kill(PID, "SIGTERM")
我正在使用 Jest as a testing library and inside its setup hook (which is executed before all my tests), I 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?
有没有最好的方法来终止在该函数内启动的进程?
谢谢!
您可以在服务器上创建启动和停止方法。这样你就不用担心分叉你的进程了。
我以快递为例。
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);
});
我目前的做法如下:
- 将 Express bootstrap 进程包装在一个函数中,returns
httpServer
实例用于使服务器侦听请求。这是beforeAll
钩子的一个很好的例子。 - 在
afterAll
. 中使用之前的参考关闭服务器
另一种选择(有点棘手)可能是在所有测试开始时启动服务器一次并在结束时关闭它:
- 直接生成节点进程而不是通过
npm
- 将进程 ID 存储在临时 mongo 的集合中(但可以是任何东西)
- 在拆解中,我检索了 PID,然后我就做
process.kill(PID, "SIGTERM")