用jasmine-node在nodejs中testingasynchronousmongodb调用

我使用jasmine-node对我的nodejs函数运行testing。 作为nodejs和mongodb的新手,我遇到的第一件事是testing一些数据库调用,由于nodejs的asynchronous特性,我立即被卡住了。

我想要做的是:

1)添加一个add函数来添加新的条目到一个mongodb表

2)从该函数接收一个状态string来validation动作的状态

以下是我的规范的代码。 在beforeEach调用我初始化数据库。 正如你在实现中看到的那样,它只是被实例化了一次,因为有一个条件询问它是否已经存在。

 var mongo = require('../mongo.js'); describe('mongo', function() { // generate a random number in order to test if the written item and the retrieved result match var randomNumber = Math.random(); var item = { 'cities': { 'london': randomNumber } }; beforeEach(function() { mongo.init(); waitsFor(function() { return mongo.getCollection(); }, "should init the database", 10000); }); it('should return "added" after adding an item to the database', function() { var result; waitsFor(function() { result = mongo.add(item); // the result value here is always undefined, // due to the problem i'm having in my implementation return result !== undefined; }, "adding an item to the database", 10000); runs(function() { expect(result).toEqual('added'); }); }); }); 

现在,对于每个数据库查询,我都可以定义一个在查询成功运行时执行的callback函数。 我不知道如何实现的是从mongodbcallback的结果。

这是数据库function的当前实现:

 var mongo = require('mongodb'), Server = mongo.Server, Db = mongo.Db; var server = new Server('localhost', 27017, {auto_reconnect: true}); var db = new Db('exampleDb', server); var collection = false; // initialize database var init = function() { if (collection === false) { db.open(dbOpenHandler); } }; var dbOpenHandler = function(err, db) { db.collection('myCollection', dbCollectionHandler); }; var dbCollectionHandler = function(err, coll) { collection = coll; }; /** returns the current db collection's status * @return object db collection */ var getCollection = function() { return collection !== false; }; /** Add a new item to the database * @param object item to be added * @return string status code */ var add = function(item) { var result = collection.insert( item, {safe: true}, function(err) { // !! PROBLEM !! // this return call returns the string back to the callee // question: how would I return this as the add function's return value return 'added'; }); }; // module's export functions exports.init = init; exports.getCollection = getCollection; exports.add = add; 

我也打开其他方法,如何在MongoDB中testing数据库调用。 我读过一些关于这个话题的文章,但是没有一篇介绍我的具体案例。

最后,在JohnnyHK的回答帮助下,我设法使它callback。 看下面的testing用例来理解我做了什么:

 it('should create a new item', function() { var response; mongo.add(item, function( err, result) { // set result to a local variable response = result; }); // wait for async call to be finished waitsFor(function() { return response !== undefined; }, 'should return a status that is not undefined', 1000); // run the assertion after response has been set runs(function() { expect(response).toEqual('added'); }); )} 

你将不得不改变你的add方法来接受一个callback参数,以便它可以通过callback传递asynchronous结果给调用者:

 var add = function(item, callback) { collection.insert(item, {safe: true}, function(err) { callback(err, 'added'); }); }; 

你现在可以用jasmine-node中的done函数干净得多了:

 it('should create a new item', function(done) { mongo.add(item, function(error, result) { expect(result).toEqual('added'); done(); }); }); 

这个testing将一直等到done()被asynchronous调用。 有5秒的默认超时,之后你的testing将失败。 你可以改变这个,比如15秒,如下所示:

 it('should create a new item', function(done) { mongo.add(item, function(error, result) { expect(result).toEqual('added'); done(); }); }, 15000);