【问题标题】:Keep MongoDB connection open while running tests using mocha framework使用 mocha 框架运行测试时保持 MongoDB 连接打开
【发布时间】:2018-08-23 19:55:35
【问题描述】:

我正在使用类似于 How to properly reuse connection to Mongodb across NodeJs application and modules 的东西来保持我的 mongoDB 连接打开。
这需要将所有代码放入 MongoDB.connectDB(async (err) => {...} 块中。
使用 Mocha 编写测试时我将如何使用它。
我必须为每个测试使用单独的连接吗?像这样?

const MongoDB = require('../src/mongoUtil') // providing access to the mongo database
var events = require('../src/events') // containing all my database Functions

describe('events.js', function () {
  describe('addEvent()', function () {
    it('should return the event, when added succesfully', async function () {
      await MongoDB.connectDB(async (err) => {
        if (err) throw err

        const database = MongoDB.getDB()
        const eventsCollection = database.db().collection('events')

        const event = {
          name: 'test Event',
          members: []
        }

        const result = await events.addEvent(eventsCollection, event)

        MongoDB.disconnectDB()

        if (result.name !== event.name) {
          return new Error('TODO')
        }
      })
    })
  })
})

如果我对 mocha 网站的理解正确,我可能还必须手动将测试设置为完成?
我可以只有一个连接吗?

mongoUtil.js

const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://localhost:27017/testing'

let _db

const connectDB = async (callback) => {
  try {
    MongoClient.connect(uri, { useNewUrlParser: true }, (err, db) => {
      _db = db
      return callback(err)
    })
  } catch (e) {
    throw e
  }
}

const getDB = () => _db

const disconnectDB = () => _db.close()

module.exports = { connectDB, getDB, disconnectDB }

events.js

const addEvent = async (collection, event) => {
  try {
    const exists = await collection.findOne({ 'name': event.name })
    if (exists) {
      return false
    } else {
      const results = await collection.insertOne(event)
      return results.ops[0]
    }
  } catch (e) {
    throw e
  }
}
module.exports = { addEvent }

【问题讨论】:

  • 我可以只有一个连接吗? - 不能。您可能想在beforeEach 中执行此操作。
  • 我想过,但这是不可能的,因为与数据库相关的所有内容都必须在 MongoDB.connectDB({...}) 块内运行。
  • src/mongoUtil 里面是什么?
  • 我已将其添加到主帖

标签: javascript node.js mongodb mocha.js


【解决方案1】:

您无需将所有内容都放入MongoDB.connectDB({...})。这被称为回调地狱,应尽可能避免。 mongoUtil 是不方便的包装器,它不会使 MongoDB API 更简单或更易于使用。

await MongoDB.connectDB(async (err) => { ... 是一个错误。将async 函数作为回调是不够的,会导致控制流不正确。

MongoClient.connect 使用错误优先回调,因此它可以与done 一起使用以将错误传递给测试套件:

let db;

beforeEach(done => {
  MongoClient.connect(uri, { useNewUrlParser: true }, (err, _db) => {
    db = _db;
    done(err);
  });
});

connectDB 错误地承诺MongoClient.connect。当 Promise 和 async..await 正在使用时,不需要一次性回调。可能是:

const connectDB = () => {
  return new Promise((resolve, reject) => {
    MongoClient.connect(uri, { useNewUrlParser: true }, (err, db) => {
      if (err) reject(err);
      else resolve(db);
    });
  });
};

但事实是mongodb 在省略回调参数时本机支持承诺。 mongoUtil 只需要一个辅助函数,connectDB

const connectDB = () => MongoClient.connect(uri, { useNewUrlParser: true });

因为它支持承诺,所以可以与 Mocha 无缝使用:

let db;

beforeEach(async () => {
  db = await connectDB();
});

afterEach(() => db.close());

close 是异步的,也返回一个承诺。

【讨论】:

  • 这解决了我的问题,谢谢。如果我想在 app.js 中使用相同的解决方案,我需要将它包装到一个异步函数中并使用 await(如你的 beforeEach 示例)或使用 .then()。我可以创建一个const main = async () => {} 函数吗?
  • 不客气。现在,应用程序入口点的常见配方是异步 IIFE,(async () => { ... })().catch(console.error)
  • 大家好 - 我处于类似情况,您在这里讨论的解决方案似乎最接近我想要的解决方案。但是,我无法让它工作。是否可以提供一个小示例来显示 app.js 文件和测试文件中的代码?我无法让测试退出,因为它没有关闭 Mongo 连接,而且我不知道如何让测试在完成运行后关闭它。我在这里发布了这个 - stackoverflow.com/questions/63759862/…
  • 我准备好了。用正确的答案更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
  • 2012-05-26
  • 2013-09-10
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-24
相关资源
最近更新 更多