我是Mocha的新手,对Node / Express只有一点经验。当我通过Express应用程序访问它时,我的DbProvider模块完美运行(mongodb)。现在我想测试一下。我已经阅读了Mocha网站和一些我能找到的教程。但是我在寻找一个可以遵循的真实世界的例子方面遇到了很大麻烦(任何链接都非常赞赏!)。
这是我尝试编写测试文件失败的原因:
var DbProvider = require('../db').DbProvider;
var assert = require('assert');
var dbProvider = new DbProvider('localhost', 27017, 'mydb');
var util = require('util');
console.log(util.inspect(dbProvider));
describe('DbProvider', function(){
describe('findAllNotes', function(){
it('should return some notes', function(){
dbProvider.findAllNotes({}, function (err, result){
assert(result.length > 0);
});
})
})
})
我得到的输出是:
$ mocha
{}
✖ 1 of 1 test failed:
1) DbProvider findAllNotes should return some notes:
TypeError: Cannot call method 'collection' of undefined
at DbProvider.doOperation (/Users/frode/Node/json/db.js:46:11)
at DbProvider.findAllNotes (/Users/frode/Node/json/db.js:56:8)
at Context.<anonymous> (/Users/frode/Node/json/test/test.js:15:18)
(cutting out the rest)
似乎我没有成功创建dbProvider。这在我的应用程序中完美运行......我怎样才能完成这项工作? (也许还有:我的设置方式一般都好吗?)
编辑:以下是db.js文件:
// Database related
'use strict';
var MongoClient = require('mongodb').MongoClient;
var BSON = require('mongodb').BSONPure;
var ObjectID = require('mongodb').ObjectID;
var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
var Validator = require('validator').Validator
var fieldMaxLength = 1024;
//var util = require('util');
var DbProvider = function(host, port, database) {
var dbUrl = "mongodb://"+host+":"+port+"/"+database;
var self = this;
MongoClient.connect(dbUrl, function(err, db) {
self.db = db;
});
};
// Do some basic validation on the data we get from the client/user
var validateParams = function(params, callback) {
// Let´ do a quick general sanity check on the length on all fields
for(var key in params) {
if(params[key].length > fieldMaxLength) callback(new Error('Field ' + key + ' is too long.'));
}
// and the let us check some specific fields better
if (params._id) {
if(checkForHexRegExp.test(params._id)) {
// In case of '_id' we also need to convert it to BSON so that mongodb can use it.
params._id = new BSON.ObjectID(params._id);
} else {
var err = {error: 'Wrong ID format'};
}
}
if(err) callback(err);
}
// Generalized function to operations on the database
// Todo: Generalize even more when user authenication is implemented
DbProvider.prototype.doOperation = function(collection, operation, params, callback) {
validateParams(params, callback);
var operationCallback = function(err, result) {
callback(err, result);
};
this.db.collection(collection, function(err, collection) {
if(operation==='find') {
collection.find().toArray(operationCallback);
} else {
collection[operation](params, operationCallback);
}
});
}
DbProvider.prototype.findAllNotes = function(params, callback) {
this.doOperation('notes', 'find', params, callback);
};
DbProvider.prototype.findNoteById = function(params, callback) {
this.doOperation('notes', 'findOne', params, callback);
};
DbProvider.prototype.saveNote = function(params, callback) {
params.created_at = new Date();
this.doOperation('notes', 'save', params, callback);
};
DbProvider.prototype.deleteNote = function(params, callback) {
this.doOperation('notes', 'remove', params, callback);
};
DbProvider.prototype.findUser = function(params, callback) {
this.doOperation('users', 'findOne', params, callback);
};
exports.DbProvider = DbProvider;
在Benjamin告诉我处理mongodb连接到数据库的异步性质之后,并且受到他关于如何调整代码的建议的启发,我将构造函数DbProvider分成两部分。第一部分,构造函数DbProvider现在只将db-parameters保存到变量中。第二部分是一个新函数,DbProvider.connect执行实际的异步连接。见下文。
var DbProvider = function(host, port, database) {
this.dbUrl = "mongodb://"+host+":"+port+"/"+database;
};
DbProvider.prototype.connect = function(callback) {
var self = this;
MongoClient.connect(this.dbUrl, function(err, db) {
self.db = db;
callback();
});
};
所以我现在可以进行像这样的Mocha测试(异步测试也需要包含“完成”,就像你在下面的代码中看到的那样):
var assert = require('assert');
var DbProvider = require('../db').DbProvider;
var dbProvider = new DbProvider('localhost', 27017, 'nki');
describe('DbProvider', function(){
describe('findAllNotes', function(){
it('should return some notes', function(done){
dbProvider.connect(function(){
dbProvider.findAllNotes({}, function (err, result){
assert(result.length > 0);
done();
});
});
})
})
})
请注意,实际测试(“应该返回一些注释”)并不值得骄傲。我想要的就是设置好让我能够测试一些东西。现在,我终于可以做到这一点,我需要编写好的测试(有一个测试数据库,清除它,测试插入文档,测试搜索文档,等等......)。 / p>
在我的Express应用程序中,我曾经像这样设置数据库:
var DbProvider = require('./db').DbProvider;
// Setup db instance
var dbProvider = new DbProvider(
process.env.mongo_host || 'localhost',
process.env.mongo_port || 27017,
process.env.mongo_db || 'nki'
);
现在我也这样做,但另外,我调用了新的connect-function:
// Connect to db. I use (for now) 1 connection for the lifetime of this app.
// And I do not use a callback when connecting here (we do in the testing)
dbProvider.connect(function(){});
Benjamin实际上指出,在Express应用程序中将数据库设置为这样可能是好的但不是最佳做法。但直到我弄清楚最佳实践是什么,我将保留这段代码。这里有几个关于我找到的主题的链接(但我还没有得出结论我将如何自己解决):
What's the best practice for MongoDB connections on Node.js?和
[node-mongodb-native] MongoDB Best practices for beginner
如果您愿意,非常欢迎您在github上关注/ fork /该项目。我的目标是尽可能准备好生产。链接是 https://github.com/frodefi/node-mongodb-json-server
答案 0 :(得分:1)
MongoClient.connect
是asynchronous。
来自文档:
回调(函数) - 执行此方法后将调用此函数。如果发生错误,第一个参数将包含Error对象,否则为null。第二个参数将包含初始化的db对象,如果发生错误则为null。
这意味着DbProvider.db
尚未在测试中设置,这就是您获得undefined
的原因。
在这里:
MongoClient.connect(dbUrl, function(err, db) {
self.db = db;
});
你告诉它“连接发生后更新self.db”,这是至少一个事件循环滴答后这个(但可能更多)。在您的mocha
代码中,您在创建.describe
实例后立即执行.it
和DbProvider
方法,这意味着它尚未初始化。
我建议您重新考虑DbProvider
以返回回调而不是构造函数。也许有些东西:
var getDbProvider = function(host, port, database,callback) {
var dbUrl = "mongodb://"+host+":"+port+"/"+database;
MongoClient.connect(dbUrl, function(err, db) {
self.db = db;
callback(db);
});
};
这也意味着将所有DBProvider
方法移动到一个对象(可能回调将返回一个dbprovider
对象而不仅仅是一个db?)。
使用单元测试解决了另一个错误:)
答案 1 :(得分:0)
这就是我使用的:https://github.com/arunoda/mocha-mongo
它为mongodb提供了一组测试助手