我正在使用Jest为Node / Express / Mongo项目设置测试。我曾尝试编写一个函数来清除集合,因此每个测试都以一个干净的平板开始:
const clearCollection = (collectionName, done) => {
const collection = mongoose.connection.collections[collectionName]
collection.drop(err => {
if (err) throw new Error(err)
else done()
)
}
beforeEach(done => {
clearCollection('users', done)
})
另一次尝试,承诺:
const clearCollection = collectionName => {
const collection = mongoose.connection.collections[collectionName]
return collection.drop()
}
beforeEach(async () => {
await clearCollection('users')
})
问题在于它们在工作和抛出错误之间交替。每次我保存文件时,它都可以正常工作,或者每次都交替抛出错误。错误始终是以下之一:
MongoError: cannot perform operation: a background operation is currently running for collection auth_test.users
MongoError: ns not found
我可以100%的时间让它工作(无论如何都受到堆栈的限制),让clearCollection()
在catch()
内调用,但这感觉很错误:
const clearCollection = collectionName => {
const collection = mongoose.connection.collections[collectionName]
return collection.drop()
.catch(() => clearCollection(collectionName))
}
答案 0 :(得分:2)
我不知道为什么beforeAll(async () => {
await User.remove({})
})
会随机抛出错误,但有一种简单的方法可以删除Mongoose中的所有文件,这对于在测试之前重置集合非常有用:
SO()
每次都有效。
答案 1 :(得分:0)
在尝试在测试开始时删除数据库并在此之后立即填充数据库时,我遇到了类似的问题。在第一次运行中,将创建集合。在下一个中,我将收到“数据库正在删除过程中”的错误。 ...而且像这样交替发生。
我还使用了“内存中” Mongodb,在运行Mocha测试之前,在单独的终端窗口中运行$ run-rs -v 4.0.0 -s
(https://www.npmjs.com/package/run-rs)。另外,我这里有Mongoose 5.2.0和Mocha 5.1.1。
我发现Mongoose不一定立即执行drop命令。相反,它将安排连接建立的时间。
因此,在某些情况下,可以解决drop命令的承诺,然后继续执行代码,直到到达创建集合的指令为止。但是drop命令尚未完成运行,并且您会在创建新集合时遇到错误。删除完成运行,并且下次运行测试时,数据库(或集合)已经删除,因此您可以再次插入新集合。
所以,这就是我解决的方法...
在前钩中运行:
test.dropDb = function(done) {
this.timeout(0)
let database = your_MongoDB_URI
mongoose.connect(database, function (err) {
if (err) throw err;
mongoose.connection.db.dropDatabase(function(err, result){
console.log('database dropping was scheduled');
});
})
mongoose.connection.on('connected', function() {
setTimeout(function(){ done() }, 3000);
});
}
在钩子之前嵌套运行
test.createDb = function(done) {
this.timeout(0)
let createDb = require('./create-db.js')
createDb() // here I call all my MyCollections.insertMany(myData)...
.then( function() {
done()
})
.catch( function(err) {
assert( null == err)
});
}
在后钩中运行
test.afterAll = function(done) {
mongoose.connection.close()
.then( function() {
done()
})
}
我不知道为什么我必须在after钩子中显式关闭连接。我想这与run-rs
的编程方式有关,但我没有对此进行研究。我只是知道,就我而言,必须在测试后关闭连接才能获得预期的行为。