对于pytest来说,下面是我用来模拟MongoDB连接的代码片段。
我的Mongo连接实用程序,它由我的所有数据层使用:
connection_util.py
from pymongo import MongoClient
mongo_connection = MongoClient()这是我的DAO层之一,用来获取学生信息:
student_dao.py
from connection_util import mongo_connection
class StudentDAO:
def get_student_info(self, student_id):
student_table = mongo_connection['test_db']['student']
student_data = student_table.find_one({"_id": student_id})
return student_data我的pytest conftest文件,其中包含mongomock连接夹具:
conftest.py
import mongomock
import pytest
@pytest.fixture(scope='class', autouse=True)
def patch_mongo():
mongo_connection = mongomock.MongoClient()
yield mongo_connection
mongo_connection.drop_database('mongodb')
mongo_connection.drop_database('testdb')
mongo_connection.close()我的测试文件。在这里,我试图用Mongomock实例来模拟实际的mongo_connection实例:
test_student.py
import connection_util
from student_dao import StudentDAO
@pytest.mark.usefixtures("patch_mongo")
class TestStudent:
def test_student(self, patch_mongo):
with patch.object(connection_util, "mongo_connection", patch_mongo):
student_id = "123546"
student = StudentDAO()
student_data = student.get_student_info("123546")
assert student_id == student_data.get("_id")在patch.object中,我的目标是connection_util,我的属性是mongo_connection,我的新变量是patch_mongo(pytest fixture)。它成功地将我的mongo_connection变量模拟为pymongo MongoClient,并在with语句中工作。但在我的studentdao.py中,它仍然指的是MongoClient,而不是mongomock MongoClient。
当我将connection_util在student_dao.py中的导入语句从"from connection_util import mongo_connection"更改为"import connection_util"并将"mongo_connection"更改为"connection_util.mongo_connection"时,它是正确工作的。下面的代码起作用。它将pymongo MongoClient替换为mongomock MongoClient。
import connection_util
class StudentDAO:
def get_student_info(self, student_id):
student_table = connection_util.mongo_connection['test_db']['student']
student_data = student_table.find_one({"_id": student_id})
return student_data这里的问题是,我不能对我的所有DAO层进行这些更改,因为有很多文件,手动执行也需要更多的时间。是否有一种不替换导入语句来模拟mongo_connection实例的方法?
发布于 2022-08-18 20:37:56
测试中的主要问题是修补错误的对象。这在打补丁的地方一节下的单元文档中有记录。
这意味着如果在模块module中使用from a import b,就必须在module中修补b的引用,例如修补module.b而不是a.b。如果您使用patch.object,这意味着使用patch.object(module, "b")而不是patch.object(a, "b")。
在您的情况下,您应该使用如下内容:
from patch_mongo import student_dao
class TestStudent:
def test_student(self, patch_mongo):
with patch.object(student_dao, "mongo_connection", patch_mongo):
student = student_dao.StudentDAO()
...请注意,出于类似的原因,我也更改了StudentDAO的导入。使用您的代码,您可以在测试模块中创建另一个StudentDAO引用,它有自己的mongo_connection引用。
还请注意,您的测试是不工作的(您从来没有设置学生数据),但我想这是由于降低了代码。
其他一些有用的链接:
顺便说一句:在很多这样的答案(包括我自己的答案)中都提到过这一点,而且我通常不会添加其他答案。这些问题的问题是总结,任何寻找类似问题的人都找不到。然而,你的问题摘要确实显示了问题所在,希望你能更容易地发现.
https://stackoverflow.com/questions/73393474
复制相似问题