十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Jest 与 MongoDB 集成指南:基于 jest-mongodb Preset 与 Global Setup/Teardown 的数据库测试方案

Jest 与 MongoDB 集成指南:基于 jest-mongodb Preset 与 Global Setup/Teardown 的数据库测试方案 Jest 与 MongoDB 集成指南基于 jest-mongodb Preset 与 Global Setup/Teardown 的数据库测试方案【免费下载链接】jestDelightful JavaScript Testing.项目地址: https://gitcode.com/gh_mirrors/je/jest本指南面向需要在 Jest 测试套件中真实读写 MongoDB 的开发者。借助 Jest 的 Global Setup/Teardown 与 Async Test Environment 能力配合shelf/jest-mongodb预设你可以在一套测试进程中自动拉起内存版 MongoDB 实例、完成数据读写断言并在收尾时自动清理全程无需手工维护数据库服务进程。读完本文你将掌握 preset 的一键接入方式、测试代码的编写规范以及该方案底层在 Jest 源码中的执行原理。为什么测试 MongoDB 代码需要专门方案单元测试通常主张隔离外部依赖但涉及数据库访问逻辑如仓储层、DAO、聚合查询时仅靠 mock 驱动会损失对真实查询语义的验证能力。Jest 对这类场景的官方建议是在测试进程的全局生命周期中启动一个真实的 MongoDB 实例让所有测试文件共享连接跑完再统一关闭。这样做的好处是测试之间天然共享同一个数据库实例无需每个文件各自起服务数据库状态由全局 Setup/Teardown 管理测试文件内部只需关注读写与断言配合 preset 的默认配置无需手动引入任何连接管理依赖。底层机制Jest 的 Global Setup/Teardown 与异步测试环境该方案能成立依赖两个 Jest 配置能力它们在本仓库的版本化文档 Configuration.md 中有完整定义globalSetupstring默认undefined指向一个自定义全局 Setup 模块该模块必须导出一个函数同步或异步均可Jest 会在所有测试文件执行前调用一次并传入globalConfig与projectConfig两个参数。globalTeardownstring默认undefined与globalSetup对称在所有测试文件执行完毕后调用一次同样接收globalConfig与projectConfig适合用来关闭数据库进程、清理临时资源。testEnvironmentnode|jsdom| string默认node指定测试运行环境MongoDB 相关预设会通过自定义环境在globalThis上注入连接信息。从本仓库源码可以确认这套生命周期的实际调度位置在 packages/jest-core/src/runJest.ts#L397-L401 中runGlobalHook({allTests, globalConfig, moduleName: globalSetup})在测试调度scheduler.scheduleTests之前被await而 packages/jest-core/src/runJest.ts#L438-L442 则在所有测试跑完之后执行globalTeardown钩子。换句话说先启动数据库 → 跑全部测试 → 再关闭数据库这正是 MongoDB 集成方案的执行模型。再看 packages/jest-core/src/runGlobalHook.ts其中值得注意的实现细节有钩子模块路径取自各测试上下文配置test.context.config[moduleName]支持多项目场景通过createScriptTransformer与requireAndTranspileModule加载并转译钩子文件随后以globalModule(globalConfig, projectConfig)方式调用若模块导出的不是函数会抛出TypeError: moduleName file must export a function at modulePath。文档还特别提醒了两个使用边界globalSetup中定义的全局变量只能在globalTeardown中读取无法在测试套件里直接访问——这正是 preset 方案需要把连接信息注入globalThis如__MONGO_URI__而不是依赖普通globals配置的原因Jest 不会对node_modules内的代码做转换因为加载转码器本身需要真实模块。另外若在globals配置项中放全局值要求其必须可被 JSON 序列化见 Configuration.md#globals-object且无法用于定义函数因此像 MongoDB 连接这种运行时对象只能通过 Setup 阶段写入globalThis完成传递。快速开始安装并接入 jest-mongodb PresetJest MongoDBnpm 包名shelf/jest-mongodb提供了运行 MongoDB 测试所需的全部配置自动下载/启动 mongod、注入连接 URI 与库名、测试结束后回收进程。接入只需三步。第一步安装预设npm install --save-dev shelf/jest-mongodb第二步在 Jest 配置中声明 preset在package.json的jest字段或jest.config.js/jest.config.ts中指定{ preset: shelf/jest-mongodb }用配置文件写法同样可以// jest.config.js const {defineConfig} require(jest); module.exports defineConfig({ preset: shelf/jest-mongodb, });第三步编写测试const {MongoClient} require(mongodb); describe(insert, () { let connection; let db; beforeAll(async () { connection await MongoClient.connect(globalThis.__MONGO_URI__, { useNewUrlParser: true, useUnifiedTopology: true, }); db await connection.db(globalThis.__MONGO_DB_NAME__); }); afterAll(async () { await connection.close(); }); it(should insert a doc into collection, async () { const users db.collection(users); const mockUser {_id: some-user-id, name: John}; await users.insertOne(mockUser); const insertedUser await users.findOne({_id: some-user-id}); expect(insertedUser).toEqual(mockUser); }); });这段测试的核心要点globalThis.__MONGO_URI__由 preset 在测试环境初始化阶段注入的 MongoDB 连接串globalThis.__MONGO_DB_NAME__preset 分配好的数据库名避免各测试文件相互污染连接在beforeAll中建立、在afterAll中关闭测试体内只做业务断言无需加载任何额外依赖——不需要你自行引入 mongodb-memory-server 之类的包preset 已把连接生命周期管理好。Preset 的解析与合并机制源码视角你可能好奇preset: shelf/jest-mongodb这一行配置背后发生了什么。在 packages/jest-config/src/normalize.ts#L171-L259 的setupPreset函数中Jest 会以jest-preset为文件名PRESET_NAME按.json/.js/.cjs/.mjs扩展名依次解析 preset 模块对应 normalize.ts#L64 与 normalize.ts#L177-L185对多项目场景强制清除模块缓存delete require.cache[...]保证每个项目拿到独立配置将 preset 中的setupFiles、setupFilesAfterEnv、moduleNameMapper、transform、globals等项与用户配置按特定顺序合并用户显式配置优先最后返回{...preset, ...options}。这也是官方文档 Configuration.md#preset-string 所描述的约定preset 必须指向一个在根目录包含jest-preset.json、jest-preset.js、jest-preset.cjs或jest-preset.mjs文件的 npm 模块也可以直接使用相对文件系统路径。shelf/jest-mongodb正是通过这一机制把启动/注入 mongod 的配置作为一份可复用的基线配置注入你的测试流程。不依赖 preset 的手动实现Global Setup 示例如果你不想引入第三方 preset例如需要固定 MongoDB 版本、多环境切换或已有 mongod 管理脚本可以基于globalSetup/globalTeardown手写等效逻辑。下面的示例摘自本仓库的 Configuration.md#globalsetup-stringmodule.exports async function (globalConfig, projectConfig) { console.log(globalConfig.testPathPatterns); console.log(projectConfig.cache); // Set reference to mongod in order to close the server during teardown. globalThis.__MONGOD__ mongod; };module.exports async function (globalConfig, projectConfig) { console.log(globalConfig.testPathPatterns); console.log(projectConfig.cache); await globalThis.__MONGOD__.stop(); };然后通过配置把它们挂到生命周期上module.exports { globalSetup: rootDir/setup.js, globalTeardown: rootDir/teardown.js, testEnvironment: node, };这套手动方案与 preset 方案的差异点在于preset 帮你完成了 mongod 的下载、启动、URI/库名注入等重复劳动而手动方案给你完全的控制权代价是需要自己负责进程管理与全局变量注入。无论哪种方式都必须遵守文档中的边界Setup 中写入globalThis的对象只能由 Teardown 读取测试文件里拿到的连接信息来自测试环境而非 Setup 的全局变量。注意事项与常见问题结合原文档与仓库实现使用该方案时有几点需要特别留意useNewUrlParser/useUnifiedTopology选项原文档示例中显式传入这两个选项它们分别对应 MongoDB Node.js Driver 的连接解析器与拓扑监控开关若你使用的 driver 版本已默认启用可省略。请以实际安装的mongodb驱动版本说明为准。全局变量不可跨测试读取globalSetup里定义的变量无法在测试套件中访问只能在globalTeardown中读取连接信息必须走testEnvironment注入globalThis的通道。globals配置须可 JSON 序列化不要在globals中存放连接对象或函数应使用setupFiles或 preset 提供的注入机制。多项目 runner 的触发条件某个项目中配置的 global setup/teardown 只在至少运行该项目的一个测试时才会触发。node_modules不参与转换hook 文件的加载虽经转换器处理但node_modules内的代码不会被 Jest 转换涉及 Babel/TypeScript 的依赖请预编译。小结Jest 对 MongoDB 的支持并非特殊内建功能而是globalSetup/globalTeardown与自定义测试环境能力的自然延伸安装shelf/jest-mongodb、声明 preset、按__MONGO_URI__/__MONGO_DB_NAME__编写测试即可获得开箱即用的真实数据库测试体验而源码中 runGlobalHook.ts 与 normalize.ts 的实现则解释了生命周期调度与预设合并的底层原理。本仓库的 e2e/global-setup 与 e2e/tests/globalSetup.test.ts 也提供了全局 Setup/Teardown 的端到端测试用例可作为深入理解该机制的参考样本。对于版本选择、MongoDB 二进制版本固定等进阶配置请查阅 jest-mongodb 自身的项目文档。【免费下载链接】jestDelightful JavaScript Testing.项目地址: https://gitcode.com/gh_mirrors/je/jest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表