如何在Jest自动化测试中启动和停止进程?

v7pvogib  于 2023-11-15  发布在  Jest
关注(0)|答案(1)|浏览(225)

我正在尝试编写一个jest自动化测试,它启动我的节点服务器,尝试连接到它,然后停止节点服务器。

import fetch from 'node-fetch';

jest.setTimeout(100000);

test('starting the root-config opens a webserver on port 9000', async () => {
  // given we have started the root-config project
  var serverProcess = require('child_process').spawn('npm run start')

  // when we request http://localhost:9000/
  var response;
  var done = false;
  while(!done) {
    try {
      response = await fetch("http://localhost:9000");
      done = true;
    } catch(e) {
    }
  }

  // terminate the server process when we're done getting a response
  serverProcess.kill('SIGKILL');

  // then we will get a 200 response
  expect(response.status).toBe(200);
});

字符串
这将可靠地启动服务器,但它很少能够停止服务器,Jest拒绝终止。

11dmarpk

11dmarpk1#

1.问题

您的库没有终止的原因可能是因为您的npm run start子进程正在产生其他进程,而这些进程在Jest关闭之前不会终止。
有几种方法可以解决这个问题,例如找到一种方法来终止这些进程,或者使用专门用于设置和拆除开发服务器的库。我将提供同步和异步解决方案,尽管我建议使用异步版本,如果您的情况允许的话,因为NodeJS的本质更像是NodeJS。

2.解决方案

2.1.同步

我最近写了kill-sync,它可以递归地杀死进程(即终止树中的所有进程):

从你的代码,而不是:

const serverProcess = require('child_process').spawn('npm run start');

// Do stuff

serverProcess.kill('SIGKILL');

字符串
您可以将其修改为:

import killSync from 'kill-sync';
import { spawn } from 'child_process';

const serverProcess = spawn('npm run start');

// Do stuff

// specify "true" for recursive 'SIGKILL' to children + grandchildren
killSync(serverProcess.pid, 'SIGKILL', true);

2.2.异步

如果你想使用异步代码,也有等价的tree-kill包。
从它的文档中,您可以如下使用它:

import kill from 'tree-kill';
import { spawn } from 'child_process';

// Do stuff

const serverProcess = spawn('npm run start');
kill(serverProcess.pid, 'SIGKILL', function(err) {
    // Do things
});

3.使用独立的Dev-server库

3.1.同步

我还写了一个名为sync-dev-server的库,它可能可以帮助解决这个问题:

从1.0.1版开始的一个基本示例是:

// const { startServer, stopServer } = require('sync-dev-server');
import { startServer, stopServer } from 'sync-dev-server';

const options = {
  // Note: all fields below are optional with set defaults
  host: 'localhost',
  port: 9000,
  timeout: 10000,
  debug: true,
  signal: 'SIGKILL',
  usedPortAction: 'ignore', // alternatives are 'kill' and 'error'
  env: {
    someKey: "someValue"
  },
}

const server = startServer('npm start', options);

// Do stuff

stopServer(server, 'SIGKILL');

3.2.异步

正如GlyphCat对你的问题的评论所暗示的,Jest puppeteer可以派上用场。特别是,有一个独立的子包jest-dev-server用于此目的。
文档显示了许多示例,我建议您查看一下。对于一个简单的用例,它可能看起来像:

import { setup, teardown } from 'jest-dev-server';

const server = await setup({
  command: 'npm start',
  launchTimeout: 5000,
  port: 3000
});

// Do stuff

teardown(server);


请注意,jest-dev-server实际上在后台使用tree-kill,类似于sync-dev-server如何利用kill-sync
我还建议您在服务器中优雅地处理适当的信号。例如,在server.js中,您可以有这样的内容:

/**
 * Handle Ctrl+C gracefully
 */
process.on('SIGINT', () => {
  server.close(() => {
    console.log('Shutting down server gracefully.');

    // 99% of the time not necessary, but I've encountered instances
    // where this was needed (I haven't looked into the reason why):
    process.exit(0);
  });
});


希望这对你有帮助:)

相关问题