Jest: 最后一次测试完成后,玩笑程序没有退出

创建于 2016-08-18  ·  60评论  ·  资料来源: facebook/jest

我在最后一次测试完成后无法完成Jest流程的问题。 用户将不得不使用ctrl-c强制退出该过程。 我的理论是测试作者不会适当地清理所有资源,但理想情况下Jest应该退出。

具体来说,我正在使用firebase-server测试Firebase,每次测试都旋转一台或多台服务器。 在afterEach动作中,我们为上次测试中创建的所有服务器调用close方法,但是即使使用此方法,Jest进程仍不会退出。

一旦测试完成(通过或失败),是否有办法强制Jest进程退出? 有没有办法获得afterAll挂钩来清除所有剩余资源? 有没有一种方法可以调试导致Jest进程退出的确切原因? 谢谢。

Enhancement Help Wanted good first issue

最有用的评论

对于阅读的任何人,您都可以使用--forceExit标志访问此功能。 🎉

所有60条评论

我们目前尚无一个好的方法。 我建议尝试挂接调试器(Chrome检查器)以了解发生了什么。 如果您知道造成异步工作的原因,则还可以通过猴子修补和跟踪它(例如在Promise.prototype.then周围放一些东西)

解决所有afterEach / after钩子后,不能强制退出异步工作吗?

我不知道如果没有处理,如何杀死现有的异步进程。

我从ava迁移而来,这不是问题,所以也许有答案吗? 也许那是Node.js中的process.exit

我想我们可以做到这一点,但我担心这会使人们在应有的情况下无法上吊,而且他们没有适当地关闭其资源。

cc @dmitriiabramov您如何看?

一个例子:我实际上是和Jest碰到这个问题的,在那我们有一个运行很长时间的观察程序,它不会终止Jest本身。 如果Jest在测试运行期间会自杀(嘿!),我将永远不会注意到这个问题,而我会提供一个在人们尝试使用它时会挂起的版本。

我不确定强制终止该过程是否安全。 同时,如果人们希望在测试完成后进行一些异步后处理,则可以使用after all挂钩,该挂钩将等待其完成后再退出该过程。

我们可能遇到的另一个问题是在完成打印之前剪切输出流。 当错误消息在进程退出之前没有足够的时间来打印时,我们就遇到了这个问题。

问题是我们是否可以找到一种方法让Jest说“看起来有些测试在完成后并没有清除。这是发生了什么事”。

after all钩子可以帮助我,但是我没有在文档中看到这样的东西(仅afterEach ),我是否缺少任何东西?

至于测试正确的清理,是否可以测试_files_是否按时完成以及是否没有使用bisect功能来隔离问题(例如在rspec中)。

好的,因此经过更多研究,这似乎是Firebase本身存在的问题,只有调用process.exit才能清除。

资源:

所有解决方法都涉及手动调用process.exit 。 恐怕在玩笑的情况下进行此操作,是否有建议在何处发出这样的电话? 我的第一个想法是:

afterAll(() => setTimeout(() => process.exit(), 1000))

…在所有测试完成运行之后一秒钟退出,以让Jest完成其工作,但是我不确定这会如何影响监视模式,如果我正确,Jest会执行一些奇特的并行处理工作,这可能会使此工作无法按预期进行。 另外,这是否是您需要在Jest中修复的东西? 如果这对于许多人来说似乎是步枪,那为什么不把它放进Jest? 或至少在“警告”模式和“杀死”模式之间切换。

我希望有一个--exit标志或某种东西(它可以是每个文件的注释之类的东西),它会在测试完成时自动关闭进程,类似于mocha。 手动关闭每个测试文件中的每个连接有点烦人。

在Codeship中运行测试时遇到了同样的问题。 它还在drone.io上失败
但是在本地它可以正常工作。

编辑:

  • 开玩笑的版本:15.1.1
  • 本地

    • 节点:6.2.2

    • npm:3.9.5

  • CodeShip

    • 节点:6.5.0

    • npm:3.10.3

  • 无人机

    • 节点:0.10.26

    • npm:1.4.3

在我看来,Firebase应该是固定的。

我对添加名为--forceExitAfterTestRun的选项没有保留,它应该很容易添加。 我认为这只需要更改即可在此处退出: https :

似乎是种种族条件。 有时在本地运行所有测试后退出,有时却没有...

在开始将Jest用于我的API规范之后,我也正在运行此程序,在这里我使用的是真实数据库而不是模拟数据库(对不起,但快照对此非常有用)。 即使添加afterAll钩子清理连接后,我仍然能够解决问题,这使我相信这与setupFiles的灯具数量有多大关系,而不是最容易调试的。

茉莉花似乎有--forceexit选项,所以如果类似的东西也会落入Jest的话,我不会抱怨

另一个问题-如果测试失败,则不会调用afterAll() ,因此不会清除任何内容,也不会关闭任何内容。 我认为--bail可以解决此问题,但我还没有尝试过

如果有人想发送公关,这是我们可以使用的一些帮助,我在之前的评论中概述了详细信息:)

如果周末有时间我会试一试。 如果有人想在那之前做它就很酷了:smile:

因刚刚开放的公关而关闭。 我们将在此处继续讨论。

对于阅读的任何人,您都可以使用--forceExit标志访问此功能。 🎉

对于Google员工:Jest不会在Jenkins CI上退出,而是在本地退出。. --forceExit确实为我修复了它。

对我来说,它忘记了使用.then(()=> {})来处理诺言-做到了

我还在为此苦苦挣扎。 我正在使用asyncawait测试API。 我连接到我的快速应用程序并ping端点,但是测试没有关闭。 我试图关闭与mongodb和服务器的连接,但它仍处于打开状态。 我只发回空的json。

就我而言,这最终是一个Firebase问题。 使用

afterAll(() => {
  firebaseApp.database().goOffline();
  firebaseApp.delete();
});

似乎可以解决问题。 我发现实际上这两行都是必需的,并且您需要使用与最初从.initializeApp()获得的相同的firebaseApp .initializeApp()

没有forceExit,有什么方法可以解决这个问题?

Jest 23包含一个名为--detectOpenHandles的标志,该标志应指向Jest无法退出的原因

--detectOpenHandles返回mongoose.connect和mongoose.model。 在afterAll中尝试mongoose.disconnect会引发mongo错误,拓扑已销毁。

screenshot 2018-06-08 11 14 51
screenshot 2018-06-08 11 14 29

@elkhan你能弄清楚如何解决猫鼬问题吗?

添加--detectOpenHandles ,Jest不仅完成了我的测试,而且没有显示任何实际上阻止Jest的内容,这很奇怪。 看起来像个错误。

对我来说, --forceExit解决了这个问题,同时我使用--detectOpenHandles但它什么也没检测到(在本地和CircleCI上)。 我还使用--runInBand

对我来说,删除--runInBand解决此问题。

--forceExit在使用shippable时也为我解决了问题...尝试了--detectOpenHandles但未给出任何结果,仍然只是导致构建挂起

添加--detectOpenHandles解决此问题,这很奇怪。

节点:v8.12.0
笑话:v23.6.0

在Codeship上运行时,添加--detectOpenHandles--forceExit不能解决我的问题。

jest --ci --verbose --forceExit --detectOpenHandle

节点:v8.12.0
笑话:v23.6.0

@sibelius避免此问题的一种方法是通过

const mongoose = require('mongoose');

mongoose.Model.init = () => {};

尽管不会创建索引,但这将阻止Jest抱怨模型。

db.collection("test-collection").add({
    title: 'post title',
    content: 'This is the test post content.',
    date: new Date(),
})
    .then(docRef => {
        console.log('Document written with ID: ', docRef);
    })
    .catch(error => {
        console.error('Error adding document: ', error);
    });

jest --forceExit --detectOpenHandle测试通过,但是.then.catch中的代码无法运行!
有任何想法吗?

@alexpchin这是我解决的方法:

    beforeAll(async (done) => {
        dbConnection = await mongoose.connect(...)
        done()
    })

    afterAll(async (done) => {
        await dbConnection.close()
        dbConnection.on('disconnected', done)
    })

使用NestJs,我必须添加

afterAll(() => {
  app.close();
});

我们发现此问题是由混乱的进程用尽了内存引起的。 添加--maxWorkers=10为我们解决了此问题。

我要添加这个原因,也许有人想知道这个问题,可能是因为我有这个原因。
我在Travis中使用Jest测试NodeJS应用程序,并且Travis一直挂起,直到Jest之后立即超时。 看来Jest没有关闭。
经过多次尝试,我发现原因是在JSm中使用了笑话。
我的jest.config.js文件中包含以下行:

  'testURL': 'http://localhost/',

这导致了Jsm的加载,并且可能无法正常关闭所有资源并使Jest保持活动状态。

我通过删除线解决了这个问题-但是玩笑会再与下面的错误失败,看到这样

SecurityError: localStorage is not available for opaque origins

为了解决这个问题,我在jest.config.js添加了以下内容:

  'testEnvironment': 'node',

希望能对任何人有所帮助。我正在添加这个原因,也许有人想知道这个问题可能是我的原因。
我在Travis中使用Jest测试NodeJS应用程序,并且Travis一直挂起,直到Jest之后立即超时。 看来Jest没有关闭。
经过多次尝试,我发现原因是在JSm中使用了笑话。
我的jest.config.js文件中包含以下行:

  'testURL': 'http://localhost/',

这导致了Jsm的加载,并且可能无法正常关闭所有资源并使Jest保持活动状态。

我通过删除线解决了这个问题-但是玩笑会再与下面的错误失败,看到这样

SecurityError: localStorage is not available for opaque origins

为了解决这个问题,我在jest.config.js添加了以下内容:

  'testEnvironment': 'node',

希望对任何人有帮助。

--forceExit --detectOpenHandles --maxWorkers = 10

为我们做了

节点:8.11.3
开玩笑23.6.0

使用NestJs,我必须添加

afterAll(() => {
  app.close();
});

只需将此处留给NestJS人员即可:
使用NestJS,我发现上面的答案确实有效。
以下是无效的:

afterAll(async () => {
        await app.close()
    })

对我来说,是--forceExit --maxWorkers=10有效(我在Ubuntu 18.04上,使用[email protected]

就我而言,使用NodeJS 10或11可以解决此问题,但是在Node 6或Node 8上仍然存在。使用--detectOpenHandles选项时什么也不会显示,而--forceExit解决此问题。

这里还有+1个人(例如@motss@seanlindo ),观察到_“ Jest在测试运行完成后一秒钟没有退出。” _在不使用--detectOpenHandles时出现。

[email protected]

在没有--detectOpenHandles情况下,测试始终会失败,但是通过并在使用--detectOpenHandles时不显示任何打开的句柄。

运行测试的机器/容器有两个内核,但是默认情况下,测试使用maxWorkers=1

当我添加--detectOpenHandles标志并使用--debug标志查看config / globalConfig时, detectOpenHandles值是_only_的不同...

如果我运行with --runInBand --detectOpenHandles测试仍然可以通过。

我可以使用以下任何一种方法来成功完成测试,而不会显示“ ...未退出...”错误:

  • jest --maxWorkers=2
  • jest --detectOpenHandles
  • jest --forceExit

现在与maxWorkers=2工作,但这只是我的观察,仅适用于将来搜索的任何人...

_Edit:其他详细信息:这仅影响我的CI环境,这是一个从alpine:3.7运行节点v8.9.3的docker容器。 我无法在开发机上使用--maxWorkers=1复制

确认我现在收到此错误。 使用--maxWorkers=10似乎可以解决此问题。

所以。。。我为此花了很长时间(使用travis ci,工作服和打字稿)。
最终将挂起并生成失败的构建(但仅在Travis CI中使用)。

经过反复的尝试和错误,我发现对我来说解决此问题的原因是我在测试中添加了一条明确的路径。

使用npm脚本失败

   "test": "jest",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

并通过(在travis ci中)与:

   "test": "jest .*\.test\.ts",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

如果您将Docker与Redhat UBI映像和create-react-app使用,请确保在运行npm test之前设置CI=true npm test

2019年12月。仅在Travis上讨论此问题。 测试在本地通过。 @qopqopqop的修复程序对我

当我们的项目开始添加使用钩子和测试库的新组件时,我才遇到此错误。 我认为Jest,测试库和React挂钩之间可能会有一些摩擦,因为它们都是新技术。 这些项目仍在学习如何相互配合。 或者,我们可能正在编写使用错误的钩子的真正错误的功能组件。 :-)

我仍然有这个问题。 我无法退出测试,这会使我的所有应用程序npm test失败。 有什么线索吗?

@koooge您可以举一个不适合您的示例吗?

要在所有测试通过后使测试退出并以0退出,您必须输入--watchAll = false
像npm运行测试---watchAll = false

这对我有用

为了使此功能与Firebase配合使用,我必须这样做:

afterAll(() => {
    firebase.app().delete();
});

我已经使用选项修复了它:

--forceExit

https://jestjs.io/docs/zh/cli# --forceexit

所以我也遇到了这个问题。 当我知道我正确地处理了所有async呼叫时,看到A worker process has failed to exit gracefully and has been force exited...警告消息很令人讨厌。 我使用--detectOpenHandles进行了测试,但没有任何显示。 经过一番研究,我发现我的罪魁祸首是Promise.race

我使用本机的Promise实用程序库(https://github.com/blend/promise-utils),并将一些外部API调用包装在timeout实用程序中。 该实用程序依次使用本地Promise.race

我提取了这些代码,并创建了一个简单的测试用例来确认我的发现。

it('promise.race', async() => {
  await Promise.race([
    new Promise((res) => setTimeout(res, 10000)),
    Promise.resolve('true')
  ])
})

假设您的测试用例超时设置为默认设置,则上述测试将始终给出警告。

不管jest用来检测引擎盖下打开的句柄的方式如何,都没有考虑到Promise.race故意打开的句柄。 该用例肯定属于假阳性类别。 我不确定这个假阳性是否可以解决,但是也许其中一位开发人员对此有巧妙的解决方案。

现在,我像其他所有人一样坚持使用--forceExit

编辑:
刚发现这个问题,似乎确实是一个更深层次的nodejs / v8问题https://github.com/nodejs/node/issues/24321

对于从Firestore测试中来到这里的其他人,这对我有用:

afterAll(async () => {
  // Shut down Firestore, otherwise jest doesn't exit cleanly
  await firestoreInstance.terminate()
});

我在使用Apollo&Jest时仍然遇到相同的问题。 不幸的是,即使选项--detectOpenHandles最终退出,它仍然使该过程花了几秒钟的时间(与它的名称相反:它不提供有关哪个句柄仍处于打开状态的信息!)。

使用--forceExit可以完成工作,但会令人讨厌地打印:

强制退出Jest:您是否考虑过使用--detectOpenHandles来检测在所有测试完成后仍在运行的异步操作?

我发现的解决方法(这绝不是解决方案!)正在向jest.config.js添加teardown

globalTeardown: '<rootDir>/__tests__/teardown.js',

在teardown.js中使用process.exit:

module.exports = async function () {
    console.log('done!');
    process.exit(0);
}

我也有这个问题。 我该如何解决? 我已经设置了forceExit: true--forceExit --detectOpenHandles --maxWorkers=10不起作用。

https://github.com/atom-ide-community/atom-ide-base/pull/33

编辑:其他地方的问题。 我正在使用的是测试运行程序...

@alusicode
这对我不起作用npm test --watchAll=false
但是它通过在package.json文件中添加--watchAll=false来工作。 👍

喜欢

"test": "react-scripts test a jest --ci --reporters=default --reporters=jest-junit --watchAll=false"

官方文档: https: //jestjs.io/docs/en/cli.html# --watchall

没有使用firebase,但是我的工作流脚本存在相同的问题。 使用不带参数的jest表示我的某些脚本没有正常关闭,我应该使用--runInBand --detectOpenHandles 。 这将解决我所有测试中的问题,除了一项(顺便说一句--detectOpenHandles没告诉我测试有问题)。
因此,我开始一个接一个地检查所有测试。 我发现有2个测试我在调用异步函数时忘记使用await
添加等待后,它已修复。 尽管我认为--detectOpenHandles不打印问题是正常的。

此页面是否有帮助?
0 / 5 - 0 等级