【问题标题】:Mocha timeouts during MongoDB connectionMongoDB 连接期间的 Mocha 超时
【发布时间】:2018-05-12 07:01:35
【问题描述】:

这里是Mongo新手。我正在尝试使用 Mocha、Chai 连接一个单元测试我的 mongo db 集合。但是每次我运行测试时,连接似乎都会超时。我已将mocha.opts 中的timeout 增加到50K ms,但连接似乎仍然超时。我找不到原因?

这是我的代码

use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const chai = require('chai');
const expect = chai.expect;



/**
 * 
 * Create a new schema that accepts a firstname and lastname and employee id
 */

 const testSchema = new Schema({
     firstname : {type: String,required:true},
     lastname : {type: String, required:true},
     id : {type : Number, required : true}
 });

 /**
  * 
  * Create a new collection name employee_details 
  */

  const employee_details = mongoose.model('employee_details',testSchema);

  describe('Create a connection with the database',()=>{
      before((done)=>{
          mongoose.connect('mongodb://127.0.0.1:27017/new_demo');
   //I tried changing the url to mongodb://localhost/new_demo but it didn't work
          const db  = mongoose.connection;
          db.on('error',console.error.bind(console,'Error connecting to DB'));
          db.once('open',()=>{
              console.log('Connected to new_demo db');
              done();
          });
      });

  });


  describe('Test Database function',()=>{
      //Save something with value Mike Stevens, 19981
      it('saves a new record',(done)=>{
        var first_record = employee_details({
            firstname : 'Mike',
            lastname : 'Stevens',
            id : 19981
        });

        first_record.save(done);
      });



      after((done)=>{
          mongoose.connection.db.dropDatabase(()=>{
              mongoose.connection.close(done);
          });
      });
  });

到目前为止我尝试过的事情

  • 增加 mocha 的超时时间
  • 将连接 URL 更改为 mongodb://localhost/new_demomongodb://localhost:27017/new_demo
  • 在 shell 中启动 mongod,然后尝试运行 mocha 测试

错误信息是

Error: Timeout of 50000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/ab/ab/abcd/api-testing/mongo-testing/my-mongo-tests/test/create_connection.js)

根据错误消息,应该调用done,这是在代码中完成的。那为什么会出现这个错误呢?

编辑 1:完整的错误消息

Test Database function
    1) saves a new record
    2) "after all" hook


  0 passing (50s)
  2 failing

  1) Test Database function
       saves a new record:
     Error: Timeout of 50000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/ab/ab/abcd/api-testing/mongo-testing/my-mongo-tests/test/create_connection.js)


  2) Test Database function
       "after all" hook:
     TypeError: Cannot read property 'dropDatabase' of undefined
      at Context.after (test/create_connection.js:56:34)

【问题讨论】:

  • 那么你实际上是在shell中运行mongod进程吗?究竟有哪些选择?单元测试实际在哪里运行?在同一台机器上还是这些可能在不同的虚拟机或类似的东西上?
  • 我只是在终端中运行mongod,没有任何选项。单元测试在同一台机器上的不同终端中运行。
  • 你不能没有选项运行,因为它在大多数情况下将无法启动。除非您创建了一个默认的数据目录名称,否则这实际上是不明智的。这是在哪个操作系统上?您至少可以从另一个终端窗口运行mongo shell 吗?想想不止一个句子作为回应,准确地展示你在做什么,并“在你自己的问题中”回答所有这些问题。问题中的详细信息而不是 cmets。

标签: javascript node.js mongodb mocha.js chai


【解决方案1】:

mocha 测试用例与普通的 JS 代码没有什么不同,因此它会遵循 JS 代码的作用域隔离和流程。我试图修复测试用例以允许在各种测试用例和前/后挂钩中进行变量访问。

请注意,我没有执行实际的测试用例,您可能需要修改下面的代码以使其成功运行

'use strict';
 const mongoose = require('mongoose');
 const Schema = mongoose.Schema;
 const chai = require('chai');
 const expect = chai.expect;



 /**
  * 
  * Create a new schema that accepts a firstname and lastname and employee id
  */
 const testSchema = new Schema({
     firstname: { type: String, required: true },
     lastname: { type: String, required: true },
     id: { type: Number, required: true }
 });

 /**
  * 
  * Create a new collection name employee_details 
  */
 const employee_details = mongoose.model('employee_details', testSchema);

 /**
  * Decalre the db const in this(global) context so this variable is visible by all test cases
  */
 const db;

 //  describe('Create a connection with the database', () => {
 //      // Seems redundet to something
 //      // Also the context is lost if you do this .. 
 //      // Thus not allowing for you to use variables .. const db in this case
 //      // If you still want this describe, you will have to use it like any other javascript function ... to expose the variables
 //  });


 describe('Test Database function', () => {

     // connect to database     
     before((done) => {
         mongoose.connect('mongodb://127.0.0.1:27017/new_demo');
         //Keep the url same which you use to debug you local application
         db = mongoose.connection;
         db.on('error', console.error.bind(console, 'Error connecting to DB'));
         db.once('open', () => {
             console.log('Connected to new_demo db');
             done();
         });
     });

     //Save something with value Mike Stevens, 19981
     it('saves a new record', (done) => {
         // Also if you want to increase the deafult timeout of a teast case
         // you will have to change the => to function(), because of the way 'this' context behaves
         // Thus : 
         //   it('saves a new record', function(done) {
         //      this.timeout(10000);
         //      .. test case code
         //   }
         var first_record = employee_details({
             firstname: 'Mike',
             lastname: 'Stevens',
             id: 19981
         });

         first_record.save(function(err) {
             if (err) return handleError(err);
             // saved!
             done();
             //I used a simple callback function instead, makes life easier and code understable
         })
     });



     after((done) => {
         mongoose.connection.db.dropDatabase(() => {
             mongoose.connection.close(done);
             // I am guessing same goes here .. 
             // keep it simple !!
         });
     });
 });

现在一些理论,理想情况下,建议或者更确切地说不在单元测试用例的范围内实际连接到数据库和/或修改外部实体的状态(因为您特别提到“它是一个单元测试用例”)。

单元测试应避免进行外部调用或调用实际的 API。我们应该对调用进行存根,并在我们的测试用例中断言调用是在我们预期的时候进行的,或者是在提供了适当的输入时进行的。

下面是一个说话的例子:

//This is myGLobalServiceLoactor which is used in actual code which is to be tested.
 myGLobalServiceLoactor = {
     database: {
         save: sinon.stub(),
         find: sinon.stub()
     }
 }

 it('to check if external method is called ', () => {
     let person_to_Save = {
         //. . . 
         //. . . 
     }
     proxyPersonInterface.savePerson(input_person).then((status) => {
         // check if our stubbeb function is called
         assert(myGLobalServiceLoactor.database.save.calledOnce);
     });

 });

您可以使用诸如Sinonrewire 之类的帮助程序库来存根和代理单元测试用例中的实际模块。 希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-20
    • 2017-06-22
    • 2022-12-28
    • 2013-01-16
    • 2017-08-01
    • 1970-01-01
    • 2020-09-02
    • 2017-03-27
    相关资源
    最近更新 更多