开玩笑不等待所有解决方案开始测试

3Do*_*Dos 9 node.js es6-promise jestjs 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!');
  });
};
Run Code Online (Sandbox Code Playgroud)

这个函数用在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();
}
Run Code Online (Sandbox Code Playgroud)

最后,我在类似的东西中使用它

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

  // describes and tests here ...
});
Run Code Online (Sandbox Code Playgroud)

无论如何,当我启动 jest 时,'Server is running, launching test suite now!'console.log 永远不会出现并且测试套件失败(因为服务器尚未运行)。为什么 jest 开始测试,因为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;
Run Code Online (Sandbox Code Playgroud)

3Do*_*Dos 10

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

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

  • 如果在某些情况下我的查询需要更多时间怎么办?我不明白为什么我必须这样做。为什么 jest 根本不等待我在 `beforeAll()` 中的所有承诺 (2认同)

Jef*_*ian 7

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

  • 花了太多时间调试同样的情况:'( (3认同)

Vic*_*tor 6

beforeAll经过多次挖掘,我找到了为什么我的测试在测试之前似乎没有运行的原因。这对某些人来说可能是显而易见的,但对我来说却不是。

如果您的外部有代码describean itor other beforeXor afterY,并且该代码依赖于 any beforeX,您将遇到此问题。

问题是您中的代码describe在任何beforeX. 因此,该代码将无法访问任何beforeX.

例如:

describe('Outer describe', () => {
    let server;
    beforeAll(async () => {
        // Set up the server before all tests...
        server = await setupServer();
    });

    describe('Inner describe', () => {
        // The below line is run before the above beforeAll, so server doesn't exist here yet!
        const queue = server.getQueue(); // Error! server.getQueue is not a function
        it('Should use the queue', () => {
            queue.getMessage(); // Test fails due to error above
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

对我来说,这似乎出乎意料,考虑到代码是在describe回调中运行的,所以我的印象是该回调最终会beforeX在当前describe.

这种行为似乎不会很快改变:https ://github.com/facebook/jest/issues/4097