Jus*_*tin 6 unit-testing mocking mongoose node.js lab
每当Mongoose模型在加载后尝试加载时,都会抛出错误,例如:
错误:uncaughtException:
Account
编译后无法覆盖模型.date = Fri Feb 26 2016 10:13:40 GMT-0700(MST),pid = 19231,uid = 502,gid = 20,cwd =/Users/me/PhpstormProjects/project,execPath =/usr/local/Cellar/node/0.12.4/bin/node,version = v5.2.0,argv = [/ usr/local/Cellar/node/0.12.4/bin/node,/ usr/local/Cellar/node0.12.4/bin/lab],rss = 73306112,heapTotal = 62168096,heapUsed = 29534752,loadavg = [1.6005859375,1.84716796875,1.8701171875],uptime = 648559 OverwriteModelError:Account
编译后无法覆盖模型.
我很好,但现在我正在为我的模型编写单元测试,我遇到了一个问题.
我将所有Mongoose模型放在文件src/models/
夹内的单独文件中,并且要加载这些模型,只需要文件夹,将Mongoose
对象传递给它,src/models/index.js
文件将加载所有模型,并返回一个对象楷模.这个index.js
文件可以在这里看到(而不是它的相关,但模型名称基本上是文件名,没有.js)
现在,模型的单元测试也分成单独的文件.每个模型都有一个测试文件.即使每个单元测试文件都关注特定模型,其中一些也使用其他模型(用于之前/之后的任务).
我刚刚创建了第二个单元测试文件,当我独立执行每个单元时,它们工作得很好.但是当我执行所有这些操作时,我收到上述错误,说明我试图多次加载模型.因为我需要./models
在每个单元测试用例中,所以我不止一次加载它们.
我想也许我可以after()
在每个单独的单元测试文件中清除所有加载的模型,如下所示:
after(function(done) {
mongoose.connection.close(function() {
mongoose.connection.models = {}
done()
})
})
Run Code Online (Sandbox Code Playgroud)
哪个根本不起作用(没有新的错误,但是一旦编译错误仍然存在,同样不能覆盖Account
模型)
而不是模型在最后一行抛出错误,当它试图返回时Mongoose.model()
,我在模型的顶部插入一些逻辑,以检查模型是否已加载,如果是,则返回该模型对象:
const thisFile = path.basename( __filename ).match( /(.*)\.js$/ )[ 1 ]
const modelName = _.chain( thisFile ).toLower().upperFirst().value()
module.exports = Mongoose => {
// Return this model, if it already exists
if( ! _.isUndefined( Mongoose.models[ modelName ] ) )
return Mongoose.models[ modelName ]
const Schema = Mongoose.Schema
const appSchema = new Schema( /* ..schema.. */)
return Mongoose.model( modelName, appSchema )
}
Run Code Online (Sandbox Code Playgroud)
我现在正在我的模型中尝试它,它似乎工作正常,(好吧意味着我没有得到上面列出的错误,说我多次加载模型)
现在每当单元测试执行时,我都会收到一个错误,每个模型显示一次错误,但错误相同:
$ lab
..................................................
...
Test script errors:
Cannot set property '0' of undefined
at emitOne (events.js:83:20)
at EventEmitter.emit (events.js:170:7)
at EventEmitter.g (events.js:261:16)
at emitNone (events.js:68:13)
at EventEmitter.emit (events.js:167:7)
Cannot set property '0' of undefined
at emitOne (events.js:83:20)
at EventEmitter.emit (events.js:170:7)
at EventEmitter.g (events.js:261:16)
at emitNone (events.js:68:13)
at EventEmitter.emit (events.js:167:7)
Cannot set property '0' of undefined
at emitOne (events.js:83:20)
at EventEmitter.emit (events.js:170:7)
at EventEmitter.g (events.js:261:16)
at emitNone (events.js:68:13)
at EventEmitter.emit (events.js:167:7)
There were 3 test script error(s).
53 tests complete
Test duration: 1028 ms
No global variable leaks detected
Run Code Online (Sandbox Code Playgroud)
在堆栈跟踪中没有太多细节可供选择.
我不确定它是否由我添加到每个模型中的代码引起,检查它是否已经加载,如果是,它将在我执行单个单元测试时显示,或者它只显示无法设置属性' 0'未定义两次(一次成功初始模型加载,然后两次接下来两次......我想)
如果有人有任何意见,我将非常感谢!谢谢
我尝试运行lab --debug
以获取更多信息,虽然它没有显示出现错误的任何堆栈跟踪,但它会使它们加倍......这很奇怪.因此,如果执行时只有2 lab
,则lab --debug
显示4
另外,我使用Winston进行日志记录.如果我将日志级别更改为debug(在控制台中显示了很多调试条目),它不会显示有关这些错误的任何条目...所以这让我觉得它可能不是由我的脚本引起的,而是某种东西在单元测试依赖项?
错误说它们来自error.js文件,但不要说太多其他内容.我试图找到一个错误.js通过find . -name 'events.js'
,没有结果..奇怪
我认为您放入每个模型中的代码都是黑客行为。在正常执行期间,require
具有“全局”作用——一旦导入该模块,就不会再导入第二次。
也许这个正常流程在测试过程中会改变,但这意味着最好找到一个可以在测试中本地实现的解决方案。
看起来您也遇到了与本期中讨论的问题类似的问题 - OverwriteModelError with mocha 'watch'。
有一些解决方案可以尝试:
1)每次创建新的猫鼬连接:
var db = mongoose.createConnection()
Run Code Online (Sandbox Code Playgroud)
2)通过nodemon运行mocha。这对我来说看起来令人费解,但仍然值得尝试,也许它使每个测试完全独立运行。我还假设您使用摩卡进行测试:
nodemon --exec "mocha -R min" test
Run Code Online (Sandbox Code Playgroud)
3)每次测试后明确mongoose模型和方案:
after(function(done){
mongoose.models = {};
mongoose.modelSchemas = {};
mongoose.connection.close();
done();
});
Run Code Online (Sandbox Code Playgroud)