【问题标题】:How to mock mongodb for python unittests?如何为 python 单元测试模拟 mongodb?
【发布时间】:2017-07-03 12:22:17
【问题描述】:

我正在使用 Python 2.7 的 mock 模块来模拟我的其他功能并使用

unittest 用于编写单元测试。

我想知道模拟 MongoDB 是否与使用模拟功能不同(mock.patch 正在调用的函数?)或者我需要为此目的使用另一个不同的包?

我认为我不想运行测试 mongodb 实例。我想要的只是一些速度数据并且能够调用pymongo 功能。我只是有点迷失在想有没有办法为模块(如pymongo)编写模拟,或者mock模块可以实现任何事情。

如果您能提供一个示例或教程,非常感谢。

要测试的代码

from pymongo import MongoClient

monog_url = 'mongodb://localhost:27017'
client = MongoClient(monog_url)
db = client.db

class Dao(object):
   def __init__(self):
      pass

   def save(self, user):
      db_doc = {
        'name': user.name,
        'email': user.email
      }
      db.users.save(db_doc)

   def getbyname(self, user):
      db_doc = {
        'name': user.name,
      }
      return db.users.find(db_doc)

为了测试这个,我真的不希望测试 mongodb 启动并运行!而且,我想我不想模拟 db.userssave 和 db.users.find 因为我希望能够真正检索我保存的数据并确保它在数据库中。我认为我需要为记忆中的每个模型创建一些 fixtures 并与它们一起使用。只是我需要一个外部工具来执行此操作吗?

我正在考虑保留一些这样的假数据,只是不知道如何正确处理。

users = { 
    {'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
    {'name': 'Sam', 'email': 'sam@gmail.com'}
}

【问题讨论】:

  • 您能否添加一些您想测试的示例代码作为提供建议的基础?
  • @KlausD。我在描述中添加了示例代码。

标签: python mongodb unit-testing mocking pymongo


【解决方案1】:

您当然可以模拟 PyMongo,但我建议模拟 MongoDB 服务器本身。我为 MongoDB 编写了一个可以完全控制的纯 Python 模拟器,它可以响应 MongoDB Wire Protocol 消息,但您可以选择:

http://mockupdb.readthedocs.io/tutorial.html

这是一个将 MockupDB 与 Python 应用程序一起使用的示例:

https://emptysqua.re/blog/test-mongodb-failures-mockupdb/

这需要对 MongoDB 有线协议有深入的了解,但无论如何这是一项有用的技能。

【讨论】:

    【解决方案2】:

    如果你只是做一些简单的事情,你也可以这样做,并且你真的不需要按字段检索。

    @mock.patch("pymongo.collection.Collection.find")
    def test_name(self, mock_find):
        mock_find.return_value = {'name' : 'Kelly', 'email' : 'kelly@gmail.com'}
        # rest of test
    

    【讨论】:

    • 如果我们想按字段检索它怎么办?像 object.field ?
    【解决方案3】:

    我推荐使用 mongomock 来模拟 mongodb。它基本上是一个带有 pymongo 接口的内存中 mongodb,专门为此目的而制作。

    https://github.com/mongomock/mongomock

    【讨论】:

    • 你有什么例子可以说明如何从 mongodb 生成模拟数据吗?我在任何地方都找不到任何文档/示例。
    • 您可以编写一个脚本来获取您想要的数据,使用 bson.json_util.dumps 将其保存在一个 json 文件中,该文件可用于您的测试,然后将数据加载到您的 setUp 函数或夹具中的 mongomock 中。
    • 对于mongomock 的新手,只需两行代码即可开始使用:import mongomockclient = mongomock.MongoClient()。之后,您可以像使用 pymongo 一样使用 client.my_db.my_coll.insert_one({'a': 1})
    【解决方案4】:

    对于包含在自定义异常中的单元测试异常,在Collectionmongomock 中修补函数(例如bulk_write

    @mock.patch("mongomock.collection.Collection.bulk_write", side_effect=BulkWriteError({}))
    def test_bulk_wrt_err(self, blk_wrt_err):
        with self.assertRaises(SpecialBulkWriteExcep) as context:
            add_user()
    

    示例代码here

    【讨论】:

      【解决方案5】:

      添加到@mirthbottle 答案,如果你想访问 mongo 对象的属性作为一个字段,你可以这样做,

      class MongoDummybject:
          def __init__(self, _data):
              for _d in _data:
                  setattr(self, _d, _data[_d])
      
      return_data = {'name' : 'Nishant', 'email' : 'nishant@gmail.com'}
      
      @mock.patch("pymongo.collection.Collection.find")
      def test_name(self, mock_find):
          mock_find.return_value = MongoDummybject(return_data)
      

      【讨论】:

        猜你喜欢
        • 2016-09-20
        • 2018-11-21
        • 2022-12-07
        • 2016-11-29
        • 2022-11-29
        • 1970-01-01
        • 1970-01-01
        • 2021-09-22
        • 1970-01-01
        相关资源
        最近更新 更多