Jest 测试由于打开的 Sequelize 连接而挂起

Jest tests hang due to open Sequelize connections

设置

我有一个 NodeJS project 使用:

Sequelize 是在加载模型模块时实例化的,该模块由一些正在使用 Jest 测试的文件导入。

问题

Jest 测试通过但随后挂起并显示消息:

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.

注意:在测试调用中添加--detectOpenHandles不影响输出。

我实际上并没有从任何测试路径调用 sequelize 对象,但是一些测试文件导入了 models 模块,因此实例化了 Sequelize。

(我还会注意到这只发生在我的 TravisCI 环境中,但我怀疑这是一个转移注意力的问题。)

背景

因为 Jest 是 运行 并行测试,所以 models 模块在整个测试过程中被加载了多次。我用调试输出证实了这一点 SEQUELIZE LOADED 当我 运行 测试时出现多次

尝试

  1. 我确实尝试在 globalTeardown 中调用 sequelize.close() 但这似乎只是打开(然后关闭)一个新的续集连接。

  2. 由于 none 的测试实际上依赖于数据库连接,因此我在导出前立即尝试在 models 模块中 运行ning sequelize.close() .这解决了问题(虽然显然不是解决方案)。

  3. 我已尝试将测试连接池配置为主动终止连接。

const sequelizeConfig = {
  ...
  pool: {
      idle: 0,
      evict: 0,
    }
}

这没有任何作用。

要求

  1. 我不想在 运行 我的测试时通过 Jest 使用暴力解决方案,例如 运行ning --forceExit。这感觉就像它忽略了根本问题,可能会让我面临其他类型的错误。

  2. 我的测试分布在数十个文件中,这意味着需要在 afterAllTests 中调用某些内容将需要大量冗余并且会引入代码味道。

问题

如何确保在测试完成后关闭 sequelize 连接,以免它们导致 Jest 挂起?

Jest 提供了一种 create universal setup before every test suite. This means it is possible to leverage Jest's afterAll 关闭 sequelize 连接池的方法,而无需手动将其包含在每个测试套件中。

package.json

中的 Jest 配置示例
  "jest": {
    ...
    "setupFilesAfterEnv": ["./src/test/suiteSetup.js"]
  }

示例suiteSetup.js

import models from '../server/models'
afterAll(() => models.sequelize.close())

// Note: in my case sequelize is exposed as an attribute of my models module.

由于 setupFilesAfterEnv 在 每个测试套件 之前加载,这确保了打开连接的每个 Jest 线程最终都会关闭该连接。

这不违反 DRY,也不依赖笨重的 --forceExit

这确实意味着将关闭可能永远不会打开的连接(这有点蛮力)但这可能是最好的选择。