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

sli*_*fty 7 postgresql node.js sequelize.js travis-ci jestjs

设置

我有一个 NodeJS项目,它使用:

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

问题

Jest 测试通过,但随后出现以下消息:

测试运行完成后,Jest 一秒钟都没有退出。

这通常意味着在您的测试中没有停止异步操作。考虑运行 Jest --detectOpenHandles来解决这个问题。

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

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

(我还会注意到这仅发生在我的 TravisCI 环境中,但我怀疑这是一个红鲱鱼。)

上下文

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

尝试

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

  2. 由于没有一个测试实际上依赖于数据库连接,我尝试在导出之前立即在模块sequelize.close()内运行models。这解决了问题(尽管显然不是解决方案)。

  3. 我试图将测试连接池配置为主动结束连接。

const sequelizeConfig = {
  ...
  pool: {
      idle: 0,
      evict: 0,
    }
}
Run Code Online (Sandbox Code Playgroud)

这没有任何作用。

要求

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

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

问题

如何确保在测试完成后关闭续集连接,这样它们就不会导致 Jest 挂起?

sli*_*fty 17

Jest 提供了一种在每个测试套件之前创建通用设置的方法。这意味着可以利用 Jest 的afterAll关闭 sequelize 连接池,而无需手动将其包含在每个测试套件中。

示例 Jest 配置 package.json

  "jest": {
    ...
    "setupFilesAfterEnv": ["./src/test/suiteSetup.js"]
  }
Run Code Online (Sandbox Code Playgroud)

例子 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.
Run Code Online (Sandbox Code Playgroud)

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

这不违反 DRY 并且不依赖于笨重的--forceExit.

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