jest"> jest"> 使用 Jest 测试 Mongoose
Jest 是 Facebook 开发的 JavaScript 运行时,通常用于测试。由于 Jest 主要用于测试 React 应用程序,因此将其用于测试 Node.js 服务器端应用程序会带来很多问题。我们强烈建议使用其他测试框架,例如 Mocha。
要抑制 Mongoose 的任何 Jest 警告,请设置 SUPPRESS_JEST_WARNINGS
环境变量
env SUPPRESS_JEST_WARNINGS=1 npm test
如果您选择深入危险水域并使用 Jest 测试 Mongoose 应用程序,那么您需要了解以下内容
推荐的 testEnvironment
如果您使用的是 Jest <=26
,请不要在测试 Mongoose 应用程序时使用 Jest 的默认 jsdom
测试环境,除非您明确测试仅使用 Mongoose 的浏览器库 的应用程序。在 Jest >=27
中,"node" 是 Jest 的默认 testEnvironment
,因此不再是问题。
jsdom
测试环境试图在 Node.js 中创建一个类似浏览器的测试环境,它带有许多令人不快的意外,例如 模拟的 setTimeout()
函数,该函数在测试结束后会静默失败。Mongoose 通常不支持 jsdom,并且预计在 jsdom
测试环境中无法正常工作。
要将您的 testEnvironment
更改为 Node.js,请将 testEnvironment
添加到您的 jest.config.js
文件中
module.exports = {
testEnvironment: 'node'
};
计时器模拟
绝对不要在测试 Mongoose 应用程序时使用 计时器模拟。如果您使用的是 Jest >=25
,这一点尤其重要,因为它会模拟 process.nextTick()
。
伪计时器会模拟 setTimeout()
和 setInterval()
等全局函数,当底层库使用这些函数时会导致问题。Mongoose 和 MongoDB Node.js 驱动程序使用这些函数来将工作推迟到事件循环的下一个滴答,以及监控与 MongoDB 服务器的连接。
如果您绝对必须使用计时器模拟,请确保在调用 useFakeTimers()
之前导入 Mongoose
// Fine for basic cases, but may still cause issues:
const mongoose = require('mongoose');
jest.useFakeTimers();
// Bad:
jest.useFakeTimers();
const mongoose = require('mongoose');
Mongoose 开发人员已经重构了代码以 避免使用 setImmediate()
将工作推迟到事件循环的下一个滴答,但我们无法合理地确保 Mongoose 依赖的每个库都不使用 setImmediate()
。
更好的替代方法是使用 sinon 创建您自己的 setTimeout()
包装器并模拟它。
// time.js
exports.setTimeout = function() {
return global.setTimeout.apply(global, arguments);
};
// Tests
const time = require('../util/time');
const sinon = require('sinon');
sinon.stub(time, 'setTimeout');
globalSetup
和 globalTeardown
不要使用 globalSetup
来调用 mongoose.connect()
或 mongoose.createConnection()
。Jest 在 单独的环境 中运行 globalSetup
,因此您无法在测试中使用在 globalSetup
中创建的任何连接。
进一步阅读
想学习如何正确测试 Mongoose 应用程序?Pluralsight 上的 使用 Node.js 和 Express 的 RESTful Web 服务 课程有一个关于使用 Mocha 测试 Mongoose 应用程序的优秀部分。