Unittest模拟修补程序在循环中随机失败

2024-09-20 04:05:25 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑到复杂性,我无法提供太多的背景,但我希望能有一些洞察/发人深省的问题来解释为什么会发生这种情况

我正在测试一个将文件加载到数据库的进程,因此我正在使用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

例如,可能有100个文件,它会成功地修补其中大部分文件,但中途会随机停止使用修补程序,并导致测试失败。哪些条件/变量可能导致此修补程序无法应用?可以应用的补丁数量是否有限制?是否应该以另一种方式应用


Tags: 文件config数据库dbreturnstackdefcontext
2条回答

我的第一条调查线将涉及来自the docs on .patch()的警告:

target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.

这是关于Where to patch的进一步解释

The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.

我会尝试找到一个破损的案例,并检查那里导入环境的状态,以确保从那里可以访问您在其他地方使用的相同导入

不要修补/模拟,而是使用repository pattern访问数据库

然后,您将拥有存储库接口的两个实现:

  • 内存中:将所有数据保留在内存中
  • 使用DB驱动程序/连接器:实际写入DB

相关问题 更多 >