我在 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)。
有一些问题:
调用
patch.object
将在您提供的任何对象上修补给定的方法。如果您在测试中调用get_db
,则code.action
调用get_db
,这是 2 个不同的对象。也许这有效?但我对此表示怀疑,所以我只是改变了它。请勿使用
code
作为模块名称。这已经是 python 中包含的模块了。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/