我正在使用nodeJS / mocha / mongoose运行异步测试,并且在运行如下所示的测试时,我不断在集合中获取重复的文档。
const assert = require('assert');
const User = require('../src/user');
describe('Duplicates records test', () => {
beforeEach((done) => {
let user = new User({ name: 'Bob'});
user.save()
.then(() => done());
});
it('Return users named Bob', (done) => {
User.find({ name: 'Bob' })
.then((users) => {
console.log(users);
done();
});
});
});
以下是我正在使用的模型:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String
});
const User = mongoose.model('user', UserSchema);
module.exports = User;
以下是运行测试的输出:
[ { _id: 5c918ca6d4b6eb4416312226, name: 'Bob', __v: 0 },
{ _id: 5c918ca6c2589d4415a4317a, name: 'Bob', __v: 0 } ]
1 passing (2s)
最后是mongodb的输出:
> db.users.find().pretty()
{ "_id" : ObjectId("5c918ca6d4b6eb4416312226"), "name" : "Bob", "__v" : 0 }
{ "_id" : ObjectId("5c918ca6c2589d4415a4317a"), "name" : "Bob", "__v" : 0 }
我在套件中有几个类似的测试,并且这似乎仅在将记录保存在beforeEach语句中时才会发生。对于为什么发生这种情况的任何见解将不胜感激。
最佳答案
之所以会发生这种情况,是因为您没有逻辑在启动下一个测试时删除先前保存的记录。
为了避免在使用nodeJS / mocha / mongoose测试时出现重复记录,您至少要在运行服务器进行测试时添加一些逻辑以删除集合。
您尚未共享您的package.json
文件,但是我建议使用一个如下所示的脚本:
"scripts": {
"test": "NODE_ENV=test nodemon --exec 'mocha --recursive -R min'"
},
因此,
NODE_ENV
是一个环境变量,环境变量用于自定义行为或对一些常量进行编码以在应用程序内部进行访问,您可以使用NODE_ENV
变量指定服务器是在开发,生产中还是在运行中。因此,这将帮助您查看是否需要清空用户集合。
为此,您可以引用变量
process.env.NODE_ENV
。无论您在哪里连接到Mongo,都想添加一个if语句,如下所示:
if (process.env.NODE_ENV !== "test") {
mongoose.connect("mongodb://localhost/user", { useMongoClient: true });
}
因此,您在这里所说的是,在开发环境中运行时,只需启动服务器并连接到数据库,而在测试环境中运行时,则需要启动服务器,连接至数据库并删除集合,但这不是解决方案。本身。
我建议创建一个单独的数据库,该数据库称为
user_test
,然后创建一个单独的帮助文件,其中包含用于连接该数据库的逻辑。因此,您将拥有两个单独的数据库。
因此,在上面的if语句中,您要说的是如果我在开发或生产环境中运行,如果它不等于测试,请连接到该数据库。如果我正在测试中运行,请不要连接到该数据库。
然后,将该测试帮助程序文件添加到将用于连接到猫鼬的应用程序中。为什么要使用单独的测试帮助文件?因为它可以更轻松地确保仅在与测试数据库建立连接后才能启动测试套件。
请记住,摩卡和猫鼬并不能很好地融合在一起,或者至少在我看来并不好。
这也很有用,因为您不必使用
if
语句包装连接字符串来检查您是否处于测试环境中。如果执行了测试帮助程序文件,那么是的,您已经在测试环境中,因此不必明确显示它。该逻辑如下所示:const mongoose = require(‘mongoose’);
before((done) => {
mongoose.connect("mongodb://localhost/user_test”, { useMongoClient: true });
});
因此,现在
user_test
数据库可以整天删除,并且不会发生任何不良情况,您不会接触开发数据,因此以后甚至可以自定义该开发数据库以包含一些您可能希望拥有的数据停在附近。您还可以放置处理程序以查看连接状态,一旦连接打开,您可以使用完成的回调,如下所示:
const mongoose = require(‘mongoose’);
before((done) => {
mongoose.connect("mongodb://localhost/user_test”, { useMongoClient: true });
mongoose.connection.once(‘open’, () => done())
});
如果有任何错误,您可以这样启动
console.warn()
:const mongoose = require(‘mongoose’);
before((done) => {
mongoose.connect("mongodb://localhost/muber_test”, { useMongoClient: true });
mongoose.connection.once(‘open’, () => done()).on(‘error’, (err) => {
console.warn(‘Warning’, error);
});
});
我喜欢这种解决方案,因为如果您将所有逻辑放在测试本身内部,则有时Mocha会在与数据库建立连接之前执行测试,这意味着所有测试都将因此失败。
几乎忘了最重要的部分,删除了该集合:
const mongoose = require(‘mongoose’);
before((done) => {
mongoose.connect("mongodb://localhost/muber_test”, { useMongoClient: true });
mongoose.connection.once(‘open’, () => done()).on(‘error’, (err) => {
console.warn(‘Warning’, error);
});
});
beforeEach((done) => {
const { users } = mongoose.connection.collections;
users.drop().then(() => done()).catch(() => done());
});
我们在其中为
catch()
使用done()
的原因是,它处理第一次运行数据库时,您还没有用户集合,这会引发错误,这就是为什么我们将其添加到处理中案子。关于node.js - 使用nodejs/mocha/mongoose测试时重复数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55252120/