jestjs / jest

Delightful JavaScript Testing.
https://jestjs.io
MIT License
44.32k stars 6.47k forks source link

Open Knex database causes open handles issues in Jest 27 #11463

Closed joshkel closed 5 months ago

joshkel commented 3 years ago

🐛 Bug Report

If a test creates an in-memory SQLite3 Knex database and doesn't destroy it, then Jest 27 hangs with the following error:

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue.

If I run with --detectOpenHandles, then Jest doesn't print any messages, but it still hangs once the tests have finished.

(This is the same issue as #9473, but it occurs in Jest 27.)

This issue only happens in Jest 27. In Jest 26 and jest-circus 26, Jest cleanly exits with no warnings.

To Reproduce

Steps to reproduce the behavior: Clone the https://github.com/joshkel/jest-knex-open-handles repository and run npm i && npm test

Downgrade to Jest 26 and note that it cleanly exits: npm i jest@^26 jest-circus@^26 && npm test

Expected behavior

Jest cleanly exits; or, if Jest doesn't cleanly exit because of the open database, then --detectOpenHandles should explain the problem.

Link to repl or repo (highly encouraged)

https://github.com/joshkel/jest-knex-open-handles

envinfo

  System:
    OS: macOS 11.4
    CPU: (8) x64 Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz
  Binaries:
    Node: 12.18.3 - ~/.nvm/versions/node/v12.18.3/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.8 - ~/.nvm/versions/node/v12.18.3/bin/npm
  npmPackages:
    jest: ^27.0.1 => 27.0.1 
joshkel commented 3 years ago

Running wtfnode shows that a timer from Knex's Tarn connection pool is what's keeping Jest from exiting:

[WTF Node?] open handles:
- File descriptors: (note: stdio always exists)
  - fd 1 (tty) (stdio)
  - fd 2 (tty) (stdio)
  - fd 0 (tty)
- Intervals:
  - (1000 ~ 1000 ms) (anonymous) @ /Users/joshkelley/src/jest-workspace/jest-knex-open-handles/node_modules/tarn/dist/Pool.js:451

Jest should probably show non-user-created resources to help troubleshoot issues like this; see this comment. (In other words, these two issues may be at least partial duplicates.)

kratos-42 commented 2 years ago

Similar behaviour occurs when a redis connection is still open. Using jest@26.4.0 version with options jest --findRelatedTests --runInBand --detectOpenHandles --forceExit it forces redis to exit/disconnect; after upgrading to jest@27.x.x, Jest complains about redis process potentially keeping it from exiting.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.

natevw commented 1 year ago

Has anyone found a great workaround for this? I found that I can call knex.destroy() in my "last" test to prevent this, but that's not a real elegant or maintainable solution since if Jest ends up running any other tests after the one I assumed would be last one to use knex, they end up failing kind of cryptically because their connection is unexpectedly broken.

kratos-42 commented 1 year ago

I found that I can call knex.destroy() in my "last" test to prevent this, but that's not a real elegant

Have you tried using global teardown?

natevw commented 1 year ago

Have you tried using global teardown?

Thanks, I think that's a near-perfect fit! Unfortunately pointing globalTeardown: './jest.teardown.ts' to a file like this:

import { knex } from "./knex/sharedConnection";

module.exports = async function () {
  await knex.destroy();
};

does not work in practice in our case because the "sharedConnection" module ends up not actually being fully shared for some reason! (i.e. the instance that gets .destroy() called on it here is not the same instance that the tests were using.) My assumption is that's on us and not a Jest-specific issue though.

kratos-42 commented 1 year ago

If that is a shared knex instance it should do the job. Why do you say it's not working? Is the exported function being triggered?

github-actions[bot] commented 6 months ago

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.

github-actions[bot] commented 5 months ago

This issue was closed because it has been stalled for 30 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.

github-actions[bot] commented 4 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.