8

jasmine-node を使用して、nodejs 関数に対してテストを実行しています。nodejs と mongodb は初めてなので、最初に遭遇したのはいくつかのデータベース呼び出しをテストすることでした。nodejs の非同期の性質のために、すぐに行き詰まりました。

私がやりたいことは次のとおりです。

1) addmongodb テーブルに新しいエントリを追加する関数を追加します。

2) その関数からステータス文字列を受け取り、アクションのステータスを確認します

以下は私の仕様のコードです。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');
        });

    }); 

});

これで、すべてのデータベース クエリに対して、クエリが正常に実行されたときに実行されるコールバック関数を定義できます。私が達成する方法がわからないのは、mongodb コールバックからの結果を仕様に戻すことです。

これは、データベース関数の現在の実装です。

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 でデータベース呼び出しをテストする方法に関する他のアプローチにもオープンです。このトピックに関する記事をたくさん読みましたが、私の特定のケースをカバーしているものはありません。

解決

最後に、JohnnyHK の回答の助けを借りて、コールバックで動作させることができました。私が何をしたかを理解するために、次のテストケースを見てください。

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');
    });

)}
4

2 に答える 2

13

donejasmine-node の関数を使用すると、これをよりきれいに行うことができます。

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

done()このテストは、が非同期的に呼び出されるまで待機します。デフォルトのタイムアウトは 5 秒で、その後はテストが失敗します。たとえば、次のように 15 秒に変更できます。

it('should create a new item', function(done) {
    mongo.add(item, function(error, result) {
        expect(result).toEqual('added');
        done();
    });
}, 15000);
于 2013-05-23T16:59:18.617 に答える
3

コールバック パラメーターを受け入れるようにメソッドを変更してadd、そのコールバックを介して呼び出し元に非同期の結果を配信できるようにする必要があります。

var add = function(item, callback) {
    collection.insert(item, {safe: true}, function(err) {
        callback(err, 'added');
    });    
};
于 2012-09-24T18:25:44.070 に答える