【问题标题】:Testing Asynchronous Mongoose Static Method with Jasmine用 Jasmine 测试异步 Mongoose 静态方法
【发布时间】:2017-01-14 04:23:21
【问题描述】:

我正在开发一个 Node.JS 游戏项目,将 Mongoose 用于我的模型并使用 Jasmine 进行测试。每个游戏都有自己的 mongodb 文档,其中包含玩家列表和地图中使用的区域。我的 Mongoose 架构之一需要一种静态方法来搜索具有可用插槽的游戏。如果没有可用的游戏,它将创建一个新游戏并将其返回。如果有可用插槽的游戏,它将返回该游戏。以下是我为此设置的方法:

GameSchema.statics.get_empty_game = function(callback){

    //get all games
    this.find({players: {$exists: true}, $where:'this.players.length<4'}, function(err, games){

        if(err) throw err;

        //if there are no games present
        if(games.length == 0){

            //get all the regions
            Region.find({}, function(err, regions){

                if(err) throw err;

                var regions_docs = [];

                //compile region ids in to array of documents
                for (var i = 0; i < regions.length; i++) {
                    regions_docs.push({_id:regions[i]._id, svg_string: regions[i].svg_string});
                }

                //greate new game with region ids
                var game = new this({
                    regions: regions_docs,
                });

                //return game
                console.log("created new game", game._id);
                return callback(game);

            });

        }else{

            console.log("found game with open slots ", game[0]._id);
            return callback(game[0]);

        }
    });
}

这是我设置的测试,用于查看当 DB 中没有游戏时该方法是否会生成游戏:

describe("get_empty_game()", function(){

    beforeAll(function(){
        Game.remove(function(err, res){
            if(err) throw err;
        });
    });

    it("gets game", function(done){

        var empty_game = "";

        Game.get_empty_game(function(res){
            empty_game = res;
        });

        console.log("empty game: ", empty_game);

        expect(empty_game._id).toBeDefined();
        expect(empty_game).not.toBe("");

        done();

    });
});

由于某种原因,这在测试中完全失败了。这是回应:

Started
.empty game:  
F

Failures:
1) Game model get_empty_game() gets game
  Message:
    Expected undefined to be defined.
  Stack:
    Error: Expected undefined to be defined.
        at Object.<anonymous> (/var/www/risk/spec/game-spec.js:40:27)
  Message:
    Expected '' not to be ''.
  Stack:
    Error: Expected '' not to be ''.
        at Object.<anonymous> (/var/www/risk/spec/game-spec.js:41:27)

2 specs, 1 failure
Finished in 0.013 seconds

我已经用 Jasmine 尝试过各种异步操作,但我通常最终会遇到异步超时错误。我是 Jasmine noobie,所以我想这归结为缺乏经验,但即使在扫描了所有相关的 StackoverFlow 帖子和 Jasmine/Mongoose 文档之后,我似乎仍然无法弄清楚。我希望这不会太模糊,如果您需要更详细的信息,请告诉我。

编辑 #1:响应 Vaterrenanburg 的茉莉花错误:

Failures:
1) Game model get_empty_game() gets new game when NO games are present in collection with less than four players
  Message:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  Stack:
    Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

2 specs, 1 failure
Finished in 5.02 seconds

编辑#2: 此处使用console.log时,显示在终端中

GameSchema.statics.get_empty_game = function(callback){

console.log("hello");

//get all games
this.find({players: {$exists: true}, $where:'this.players.length<4'}, function(err, games){

    if(err) return callback(err);

但是放在这里的时候却没有出现:

GameSchema.statics.get_empty_game = function(callback){

//get all games
this.find({players: {$exists: true}, $where:'this.players.length<4'}, function(err, games){

    console.log("hello");

    if(err) return callback(err);

编辑 #3 尝试 $lt 索引后仍然无法正常工作,但我发现了其他有趣的东西。运行以下命令时:

this.find({}, function(err, games){
    if(err) return callback(err);

    console.log("games:", games);
    return callback(games);
});

尽管它是一个简单的查询,不应该花费太长时间来执行并且应该至少返回一个空数组,但我仍然会收到未定义的错误。这可能与 Jasmine 配置有关吗?

【问题讨论】:

  • 能否也包括 GameSchema 的定义?这可能是影响您的查询性能的原因。

标签: node.js mongodb mongoose jasmine


【解决方案1】:

尝试将您的断言放入回调函数中,如下所示:

    it("gets game", function(done){

        Game.get_empty_game(function(empty_game){

            console.log("empty game: ", empty_game);

            expect(empty_game._id).toBeDefined();
            expect(empty_game).not.toBe("");

            done();
        });
    });

这样,您将在 get_empty_game 方法完成后进行测试。

更新

为了响应您的新错误,请尝试将您的静态架构方法中的所有 if(err) throw err; 语句转换为 if(err) return callback(err);,这样回调始终会被执行。

另外,我注意到您的代码中还有一个小错误:在最后一个 else 块中,您应该使用 games 变量而不是 game

    }else{

        console.log("found game with open slots ", games[0]._id);
        return callback(games[0]);

    }

更新 #2

您的猫鼬查询似乎执行时间过长。 $where 片段运行任意 javascript,因此它无法利用任何索引。这可能是导致您的查询运行如此缓慢的原因。试试把它改成这个,看看你的测试是否能及时完成:

this.find({players: {$exists: true}, 'players.length':{$lt: 4}}, function(err, games){

【讨论】:

  • 我已经尝试过了,但是我得到了一个异步超时错误:失败:1) 当集合中没有少于四个玩家的游戏时,游戏模型 get_empty_game() 获取新游戏消息:错误:超时- 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时时间内未调用异步回调。堆栈:错误:超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调。在 Timer.listOnTimeout [as ontimeout] (timers.js:110:15) 2 个规范,1 个失败在 5.02 秒内完成
  • 抱歉,我是 StackOveflow 的新手,我已将错误放入我的 OP 中。
  • 响应您的更新,我已经尝试了您的更改,但我仍然收到第一个错误。此外,很好地抓住了那个错字。我发现了一些值得注意的东西,你可以在我的 OP 中找到它。顺便说一句,如何在注释中写出代码?
  • 您可以用反引号 (`) 将评论中的文本括起来以将其格式化为代码。
  • 不,我得到相同的“未定义”错误。我将放弃在 cmets 中添加代码,所以我在 OP 中添加了另一个更新
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
  • 2020-08-03
  • 1970-01-01
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多