python - 当从另一个函数调用 mongodb 时如何模拟 mongodb?

标签 python mongodb unit-testing mocking mongomock

我在 mock mongodb 时需要帮助。我正在使用mongomock模拟 mongodb。

我的项目结构是:

-- my_mongo.py
-- code.py
-- my_test.py

my_mongo.py 有:

from pymongo import MongoClient

 def get_db():
   client = MongoClient(os.environ['MONGODB_URI'])
   db = client['my_db']
   return db

 def insert(id, data):
     return get_db().results.insert_one(
          {
          "id": id,
          "data":df.to_json(),
          }).id

code.py

import my_mongo

def action():
    #do somethings
    my_mongo.insert(id, data)

my_test.py

import mongomock
import my_mongo
from unittest import mock


with patch.object(my_mongo.get_db().client, "client",  mongomock.MongoClient()):
    import code

def test_action_1():
    my_mongo.insert = mock.Mock(return_value=1)
    code.action()   

def test_action_2():
     with patch.object(my_mongo.get_db(), "get_db", mongomock.MongoClient().db):
     code.action()

这两个测试都会抛出 pymongo.errors.ServerSelectionTimeoutError 。所以,它仍然进入 my_mongo.py 中的 insert_one() 方法。 我期望在 test_action_1 my_mongo.insert 中返回 1,但事实并非如此。

我错过了什么?

最佳答案

我不完全确定 mongomock 的用途,但看起来它是用于模拟整个 mongo 数据库,而不是实际使用 python 模拟。我将在不包含 mongomock 的情况下回答,因为我认为您并不真正需要它,因此您可以接受它的值(value)。

有一些问题:

  1. 调用 patch.object 将在您提供的任何对象上修补给定的方法。如果您在测试中调用 get_db,则 code.action 调用 get_db,这是 2 个不同的对象。也许这有效?但我对此表示怀疑,所以我只是改变了它。

  2. 请勿使用 code 作为模块名称。这已经是 python 中包含的模块了。

  3. code.action 缺少参数和 return 语句。

您还会注意到,我更改了模拟的方式和内容,以说明完成模拟的不同方法。测试 1 使用函数装饰器模拟 insert 调用。测试 2 使用 contextmanager 模拟 get_db 调用。两者都是正确的,只是表明您有选择。

成品如下:

<小时/>

my_mongo.py:

from pymongo import MongoClient

def get_db():
    client = MongoClient(os.environ['MONGODB_URI'])
    db = client['my_db']
    return db

def insert(id, data):
    return get_db().results.insert_one({"id": id, "data":data.to_json()}).id  # df was undefined, updated to data
<小时/>

my_code.py:

import my_mongo

# I added id and data args. They were undefined
def action(id, data):
    return my_mongo.insert(id, data)  # I added a return here
<小时/>

my_test.py

from unittest import mock

import my_code

# I removed the contextmanager import. Nothing is being evaluated here that would
# need to be patched, so I'm pretty certain it has no effect

@mock.patch('my_mongo.insert')
def test_action_1(mock_insert):
    expected_id = 1
    mock_insert.return_value = expected_id
    ret = my_code.action(expected_id, mock.Mock())
    assert ret == expected_id

def test_action_2():
    with mock.patch('my_mongo.get_db') as mock_get_db:
        expected_id = 'some id'
        mock_db = mock.Mock()
        mock_db.results.insert_one.return_value.id = expected_id
        mock_get_db.return_value = mock_db
        ret = my_code.action(expected_id, mock.Mock())
    assert ret == expected_id

关于python - 当从另一个函数调用 mongodb 时如何模拟 mongodb?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53816215/

相关文章:

python - 确定 Python 进程的标准输出是否被重定向

spring - 使用 Spring Data MongoDB 查询纯 BSON

java - 使用 java 从 MongoDB 提取时处理空值

unit-testing - 我是否应该在类中添加功能只是为了使其可测试?

javascript - 递归 Python 函数转换为 Javascript 不起作用,数组问题

python - 如何根据第一个索引 pandas df 中的字符串删除行

python - 您的服务器套接字监听积压限制为 100 个连接

c++ - 编译我的代码以通过 xcode 在 OSX 中使用 mongodb c 驱动程序

c# - 使用 Rhino-Mock stub 的排序方法返回值

c# - 我如何从下面的代码中编写 TDD 代码?