python - pytest 模拟 MongoReplicaSetClient 对象的 .count() 和 .find() 函数
问题描述
我有一个名为 commons.py 的脚本,其中包含一些最常用的功能。
在我的主脚本中,我正在创建一个 mongo 连接对象:
db_ob = commons.db_connection()
db_connection 返回一个 MongoReplicaSetClient 连接对象。
如何为我的以下功能编写测试用例?
def check_entries():
try:
db_ob = commons.db_connection()
except:
print('Unable to connect to db!!')
return False
db_name = 'my_db_name'
collection_name = 'my_collection_name'
db_data = db_ob[db_name][collection_name].find()
if db_data.count() == 0:
print('No entries found in the collection!')
return False
return True
我可以模拟我的 db_connection 函数,但在模拟 .count() 和 .find() 函数时遇到问题。
解决方案
当结果集为空时模拟光标以测试案例的示例:
from unittest.mock import patch, MagicMock
from pymongo.mongo_replica_set_client import MongoReplicaSetClient
from pymongo.cursor import Cursor
import testee
def test_empty_result_set():
db_data_mock = MagicMock(spec=Cursor)() # 1
db_data_mock.count.return_value = 0 # 2
db_conn_mock = MagicMock(spec=MongoReplicaSetClient)() # 3
db_conn_mock.__getitem__().__getitem__().find.return_value = db_data_mock
with patch('commons.db_connection', return_value=db_conn_mock): # 4
assert not testee.check_entries() # 5
细节:
MagicMock(spec=Cursor)
返回一个模仿类的pymongo.cursor.Cursor
类。db_data_mock
是这个模拟类的一个实例。db_data_mock.count.return_value = 0
模拟该count
方法,因此它始终返回零。接下来的两行:为
pymongo.mongo_replica_set_client.MongoReplicaSetClient
(与 1. 中的方法相同)创建一个模拟实例并将光标模拟实例连接到它,以便该find()
方法始终返回db_data_mock
我们之前创建的实例。- 最后,用
commons.db_connection
返回我们的MongoReplicaSetClient
模拟对象的模拟函数替换该函数。 - 一切准备就绪;做实际测试。
unittest
更新:评论中要求进行不使用的测试
如果出于某种奇怪的“纯粹性”原因,您不想接触unittest
代码,则必须为此找到替代库,或者自己编写模拟。pytest
不提供开箱即用的模拟功能。上面没有的示例unittest
可能如下所示:
from collections import defaultdict
import testee
class CursorMock:
def count(self):
return 0
class ConnectionMock:
def find(self):
return CursorMock()
class MongoReplicaSetClientMock:
def __getitem__(self, name):
return defaultdict(ConnectionMock)
def db_connection_mock(*args, **kwargs):
return MongoReplicaSetClientMock()
def test_empty_result_set(monkeypatch):
monkeypatch.setattr(commons, 'db_connection', db_connection_mock)
assert not testee.check_entries()
代替夹具unittest.mock.patch
被使用。monkeypatch
请注意,尽管有一些pytest
提供模拟功能的插件(例如,pytest-mock
),但我所知道的大多数只是方便的包装器,unittest.mock
并且仍然在引擎盖下使用它。
推荐阅读
- mongodb - Robo 3T 错误:无法连接到任何 X 显示器
- python - FileNotFoundError: [WinError 2] 尝试使用 pysndfx 时系统找不到指定的文件
- javascript - 如何将裁剪的图像从 Ionic 4 中的 imageCropper 上传到 Firebase 实时数据库
- java - 为什么不更新 Android 中的 UI 元素
- typescript - forkJoin 不会等待所有可观察对象完成
- javascript - 防止javascript点击事件激活表单提交
- laravel - 在 Laravel 上找出路由所需的标头的理想方法是什么?
- java - 我在 JFrame 中添加容器时遇到问题
- python-3.x - 将各种字符串更改为时间戳 Python 3?
- deep-learning - DQN 不稳定预测