【问题标题】:Unit test Node w/ MongoDb - wait for Mongodb connection带有 MongoDb 的单元测试节点 - 等待 Mongodb 连接
【发布时间】:2016-06-24 18:21:04
【问题描述】:

我是单元测试节点和 mongodb 的新手......我正在尝试测试 getUsername(),但我得到了 TypeError: user.find is not a function。我相信这可能是一种竞争条件,在第一个 it 块运行之前,db-init.js 脚本没有及时与数据库建立连接。

需要明确的是,测试之外的代码没有问题。在测试之外,一切正常。

有什么建议吗?

测试:

var api = require('../app/js/api');
var httpMocks = require('node-mocks-http');


var req;
var res;


describe('db calls', function() {
  beforeEach(function() {
    api.initDBcursor();
    req = httpMocks.createRequest({
      params: { username: "foo" }
    }); 
    res = httpMocks.createResponse();
  });

  it('should get username',
     function(done) {
       api.getUsername(req, res);
       console.log(res);
   });
});

api.js

var mongo = require('../data/db-init');

var user;

function initDBcursor() {
  user = mongo.collections.user;
}


function getUsername(req, res) {
  console.log(user);
  var document = user.find(req.params.username); //HERE IS WHERE IT ERRORS
  _returnApi(document, res);
}

users.js

User.prototype.find = function(user) {
  return this.collection.find(user).limit(1).next();
};

db-init.js

var MongoClient = require('mongodb').MongoClient;
var User = require('./models/users');
var db;

var collections = {
  user: false //THIS SHOULD HAVE A VALUE FROM initCollections() BEFORE
              //BEFORE THE FIRST IT BLOCK RUNS       
};

function connect() {
  var dbURI = 'mongodb://web-app:web-app@localhost/web-app';
  return MongoClient.connect(dbURI)
    .then(function(_db) {
      db = _db;
      console.log(colors
        .bold('MongoDB default connection open to ' + dbURI));
      initCollections();
    })
    .catch(function(err) {
      console.log(colors
        .red(err));
    });
}

function initCollections() {
  collections.user = new User(db);
}

【问题讨论】:

  • 基本上,您正在尝试“推出自己的”ODM,并且不会是第一个这样做的人。因此,当您认为使用的 MongoClient.connect() 旨在处理承诺或回调时,有明确和基本的原因。对其他类似问题的一般建议也适用于您。看看mongoose 代码库。它具有在没有承诺/回调链的情况下启动连接的概念,并且像您尝试做的那样建立了“模型”。然后了解它是如何处理这种连接的,并不是你想象的那样。

标签: node.js mongodb unit-testing mocha.js


【解决方案1】:

我让它工作了。休息一下,理清思路后,我意识到我并没有启动数据库。

感谢您的建议,但对我来说重要的是不要更改原始代码。根据自己给定的规则,我从不更改代码库以适应测试。

另外,在谷歌搜索和阅读异步 mocha 文档后,我找到了一种让它在 mocha 中等待的方法。这是一个快速而肮脏的解决方案,我在它工作的地方写了......

var api = require('../app/js/api');
var yo = require('../app/data/db-init');
var httpMocks = require('node-mocks-http');

 describe('db calls', function() {
  beforeEach(function(done) {
    this.timeout(0)

    yo.connect().then(function() {
      api.initDBcursor();
    });

    setTimeout(function() {
      done()
    }, 5000);

    req = httpMocks.createRequest({
      params: { username: "foo" }
    });
    res = httpMocks.createResponse();
  });

更新 尝试各种方法后...我发现使用SuperTest 和/或Chai Http 将为您处理异步处理,减少测试的代码库。但是,不利的一面是,您实际上将运行一个节点服务器,但速度会稍慢一些。

【讨论】:

    【解决方案2】:

    尝试通过before 函数中的done 进行如下操作,而不在beforeEach 中创建连接,这将为每个测试用例建立新的连接。以下是一些示例代码。

    test.js

      before(function(done) {
        api.initDBcursor(done);
      });
    

    api.js

    function initDBcursor(cb) {
      //user = mongo.collections.user;
      mongo.connect(cb);
    }
    

    db-init.js

    exports.connect = function (cb) {
      var dbURI = 'mongodb://web-app:web-app@localhost/web-app';
      return MongoClient.connect(dbURI)
        .then(function(_db) {
          db = _db;
          console.log(colors
            .bold('MongoDB default connection open to ' + dbURI));
          initCollections();
          cb && cb();
        })
        .catch(function(err) {
          console.log(colors
            .red(err));
          cb && cb(err);
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-01
      • 2019-02-18
      • 2022-01-21
      相关资源
      最近更新 更多