我在嘲笑mongoDB时需要帮助。我正在使用蒙哥诺克来模拟mongodb。
我的项目结构是:
- my_mongo.py
- code.py
- my_test.py
my_mongo.py has:
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
回答,因为我认为您真的不需要它,所以您可以以它的价值来接受。
有一些问题:
-
调用
patch.object
将在您给它的任何对象上修补给定方法。如果您在测试中调用get_db
,则code.action
调用get_db
,这些是2个不同的对象。也许有效?但是我怀疑了,所以我只是改变了它。 -
不要使用
code
作为模块名称。这已经是Python包含的模块。 -
code.action
缺少ARG和一个返回语句。
您还会注意到,我改变了嘲笑的方式以及如何说明完成模拟的不同方法。测试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
用于修补mongoDB的代码行是错误的。您不应使用patch.object(my_mongo.get_db(), "get_db", mongomock.MongoClient().db)
,而是使用patch.object("my_mongo.get_db", return_value=mongomock.MongoClient()['my_db'])
。
以下是您示例的完整可运行代码:
my_test.py
import mongomock
from unittest.mock import patch
import my_code
import my_mongo
def test_action_2():
mocked_mongo = mongomock.MongoClient()
with patch("my_mongo.get_db", return_value=mongomock.MongoClient()['my_db']):
my_code.action()
assert mocked_mongo.my_db.results.count_documents({'id': 'some_id'}) == 1
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,
})
my_code.py
import my_mongo
def action():
#do somethings
return my_mongo.insert('some_id', '{"a": 3}')