开玩笑不要等所有决议开始测试

时间:2019-03-20 10:56:25

标签: node.js jestjs es6-promise frisby.js

我要测试的内容:快递服务器端点

我的目标:在单个脚本中自动执行API测试

我的工作:我在NodeJS子进程中启动Express服务器,并希望在运行测试套件(frisby.js端点测试)之前等待它启动。

哪些功能无法正常运行:在Promise解决方案之前启动了测试套件

我依靠wait-on软件包,一旦资源可用,服务器就会轮询并解析。

const awaitServer = async () => {
  await waitOn({
    resources: [`http://localhost:${PORT}`],
    interval: 1000,
  }).then(() => {
    console.log('Server is running, launching test suite now!');
  });
};

startServer函数中使用了此函数:

const startServer = async () => {
  console.log(`Launching server http://localhost:${PORT} ...`);

  // npmRunScripts is a thin wrapper around child_process.exec to easily access node_modules/.bin like in package.json scripts
  await npmRunScripts(
    `cross-env PORT=${PORT} node -r ts-node/register -r dotenv/config src/index.ts dotenv_config_path=.env-tests`
  );

  await awaitServer();
}

最后,我用类似的东西

describe('Endpoints' () => {
  beforeAll(startTestServer);

  // describes and tests here ...
});

无论如何,当我开玩笑时,'Server is running, launching test suite now!' console.log永远不会显示出来,并且测试套件也会失败(因为服务器尚未运行)。为什么开玩笑地开始测试,因为awaitServer显然还没有解决?

npmRunScripts函数可以正常运行,因为测试服务器已启动并在测试失败后不久运行。出于这个问题,这是npmRunScripts如何解决的问题:

// From https://humanwhocodes.com/blog/2016/03/mimicking-npm-script-in-node-js/
const { exec } = require('child_process');
const { delimiter, join } = require('path');

const env = { ...process.env };
const binPath = join(__dirname, '../..', 'node_modules', '.bin');

env.PATH = `${binPath}${delimiter}${env.PATH}`;

/**
 * Executes a CLI command with `./node_modules/.bin` in the scope like you
 * would use in the `scripts` sections of a `package.json`
 * @param cmd The actual command
 */
const npmRunScripts = (cmd, resolveProcess = false) =>
  new Promise((resolve, reject) => {
    if (typeof cmd !== 'string') {
      reject(
        new TypeError(
          `npmRunScripts Error: cmd is a "${typeof cmd}", "string" expected.`
        )
      );
      return;
    }

    if (cmd === '') {
      reject(
        new Error(`npmRunScripts Error: No command provided (cmd is empty).`)
      );
      return;
    }

    const subProcess = exec(
      cmd,
      { cwd: process.cwd(), env }
    );

    if (resolveProcess) {
      resolve(subProcess);
    } else {
      const cleanUp = () => {
        subProcess.stdout.removeAllListeners();
        subProcess.stderr.removeAllListeners();
      };

      subProcess.stdout.on('data', (data) => {
        resolve(data);
        cleanUp();
      });
      subProcess.stderr.on('data', (data) => {
        reject(data);
        cleanUp();
      });
    }
  });

module.exports = npmRunScripts;

3 个答案:

答案 0 :(得分:1)

我找到了解决方案。在尝试了几乎所有内容之后,我没有意识到开玩笑的超时设置默认为5秒。所以我增加了这个超时时间,现在测试等待服务器承诺解决。

我只是在测试套件之前添加了jest.setTimeout(3 * 60 * 1000);

答案 1 :(得分:0)

就我而言,这是由beforeAll部分的缺陷引起的。确保beforeAll不包含任何未捕获的异常,否则它将表现为测试已开始而无需等待beforeAll解析。

答案 2 :(得分:0)

在较新版本的jest中(至少> 1.3.1),您可以将done函数传递给beforeAll函数,并在完成所有操作后调用它:

beforeAll(async (done) => {
  await myAsyncFunc();
  done();
})
it("Some test", async () => {
  // Runs after beforeAll
})

此处有更多讨论:https://github.com/facebook/jest/issues/1256