鉴于复杂性,无法提供太多背景信息,但是我希望就为什么会发生这种情况有一些见解/发人深省的问题。
我正在测试一个将文件加载到数据库中的过程,因此我正在使用unittest.mock.patch
修补数据库连接的凭据,以使用测试凭据而不是生产凭据。我们提供了一系列模拟,将其作为contextmanager
的简化版本应用于此处:
from contextlib import ExitStack
def context_stack(contexts):
stack = ExitStack()
for context in contexts:
stack.enter_context(context)
return stack
def patch_mocks():
mocks = [
patch('db_config.ReadWrite', db_mocks.ReadWrite),
patch('db_config.ReadWrite', db_mocks.ReadWrite)
]
return context_stack(mocks)
它被这样使用(简化):
with patch_mocks():
LoadFiles(file_list)
LoadFiles
将遍历file_list
中的每个文件,并尝试将内容插入数据库。底层方法使用db_config.ReadWrite
连接到数据库,但是当然它们由db_mocks.ReadWrite
修补。除了看起来很随机外,此操作一直很稳定,但会失败,因为尝试创建连接时尝试使用db_config.ReadWrite
。
因此,例如,可能有一百个文件,它将成功修补其中的大多数文件,但是在中途它会随机停止使用该修补程序,从而使测试失败。哪些条件/变量可能导致此补丁不被应用?可以应用的补丁数量是否有限制?应该以其他方式应用吗?
答案 0 :(得分:1)
我的第一行调查将涉及来自the docs on .patch()的警告:
target应该是“ package.module.ClassName”形式的字符串。导入目标并将指定的对象替换为新对象,因此目标必须可从您从其调用patch()的环境中导入。 目标是在执行修饰功能时而不是在修饰时导入的。
以及有关Where to patch
的进一步说明基本原理是,您修补查找对象的位置,该对象不一定与定义对象的位置相同。
我会尝试查找一个破损的情况,并检查那里的导入环境的状态,以确保从那里可以访问您在其他任何地方使用的相同导入。
答案 1 :(得分:0)
请勿打补丁/模拟,而应使用repository pattern访问数据库。
然后您将具有Repository接口的两种实现: