开玩笑不等待所有分辨率开始测试
jest doesn't wait beforeAll resolution to start tests
我测试的内容:一个快速服务器端点
我的目标:在单个脚本中自动执行 API 测试
我做什么:我在 NodeJS 子进程中启动快速服务器,并希望在测试套件 运行 之前等待它启动( frisby.js 端点测试)
什么没有按预期工作:测试套件在 Promise 解析之前启动
我依赖 wait-on
包,一旦资源 is/are 可用,服务器就会进行轮询和解析。
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 ...
});
无论如何,当我启动 jest 时,'Server is running, launching test suite now!'
console.log 从未出现并且测试套件失败(因为服务器尚未 运行ning)。 awaitServer
显然还没有解决,为什么 jest 开始测试?
npmRunScripts
功能在测试服务器启动时工作正常,并且在测试失败后不久 运行ning。为了这个问题,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;
我找到了解决方案。在尝试了几乎所有方法之后,我没有意识到 jest 有一个默认为 5 秒的超时设置。所以我增加了这个超时,现在测试等待服务器承诺解决。
我只是在测试套件之前添加了jest.setTimeout(3 * 60 * 1000);
。
在我的例子中,它是由 beforeAll
部分的缺陷引起的。确保 beforeAll
不包含任何未捕获的异常,否则它将表现为测试开始而不等待 beforeAll
解决。
在较新版本的 jest(至少 >1.3.1)中,您可以将 done
函数传递给您的 beforeAll
函数,并在一切完成后调用它:
beforeAll(async (done) => {
await myAsyncFunc();
done();
})
it("Some test", async () => {
// Runs after beforeAll
})
经过大量挖掘,我找到了为什么我的 beforeAll
在测试前似乎没有 运行ning 的原因。这对某些人来说可能是显而易见的,但对我而言并非如此。
如果您的 describe
中的代码位于 it
或其他 beforeX
或 afterY
之外,并且该代码依赖于任何 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
});
});
});
对我来说这似乎出乎意料,考虑到 describe
回调中的代码是 运行,所以我的印象是回调毕竟是 运行 beforeX
在当前 describe
.
之外
似乎这种行为不会很快改变:https://github.com/facebook/jest/issues/4097
我测试的内容:一个快速服务器端点
我的目标:在单个脚本中自动执行 API 测试
我做什么:我在 NodeJS 子进程中启动快速服务器,并希望在测试套件 运行 之前等待它启动( frisby.js 端点测试)
什么没有按预期工作:测试套件在 Promise 解析之前启动
我依赖 wait-on
包,一旦资源 is/are 可用,服务器就会进行轮询和解析。
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 ...
});
无论如何,当我启动 jest 时,'Server is running, launching test suite now!'
console.log 从未出现并且测试套件失败(因为服务器尚未 运行ning)。 awaitServer
显然还没有解决,为什么 jest 开始测试?
npmRunScripts
功能在测试服务器启动时工作正常,并且在测试失败后不久 运行ning。为了这个问题,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;
我找到了解决方案。在尝试了几乎所有方法之后,我没有意识到 jest 有一个默认为 5 秒的超时设置。所以我增加了这个超时,现在测试等待服务器承诺解决。
我只是在测试套件之前添加了jest.setTimeout(3 * 60 * 1000);
。
在我的例子中,它是由 beforeAll
部分的缺陷引起的。确保 beforeAll
不包含任何未捕获的异常,否则它将表现为测试开始而不等待 beforeAll
解决。
在较新版本的 jest(至少 >1.3.1)中,您可以将 done
函数传递给您的 beforeAll
函数,并在一切完成后调用它:
beforeAll(async (done) => {
await myAsyncFunc();
done();
})
it("Some test", async () => {
// Runs after beforeAll
})
经过大量挖掘,我找到了为什么我的 beforeAll
在测试前似乎没有 运行ning 的原因。这对某些人来说可能是显而易见的,但对我而言并非如此。
如果您的 describe
中的代码位于 it
或其他 beforeX
或 afterY
之外,并且该代码依赖于任何 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
});
});
});
对我来说这似乎出乎意料,考虑到 describe
回调中的代码是 运行,所以我的印象是回调毕竟是 运行 beforeX
在当前 describe
.
似乎这种行为不会很快改变:https://github.com/facebook/jest/issues/4097