gpt4 book ai didi

Python:在模拟补丁类装饰器上调用停止

转载 作者:太空狗 更新时间:2023-10-29 22:30:22 24 4
gpt4 key购买 nike

模拟 documentation描述了一种将补丁应用到 TestCase 中所有测试方法的简单而优雅的方法:

@patch('foo.bar')
@patch('foo.baz')
@patch('foo.quux')
@patch('foo.narf')
class FooTest(TestCase):

def test_foo(self, bar, baz, quux, narf):
""" foo """
self.assertTrue(False)

但是,我在使用此方法时遇到的一个问题是,如果我想在其中一种测试方法中的某个补丁上调用 stop(),似乎无论如何都无法获得引用到修补程序对象——唯一传递到方法中的是模拟对象,在本例中为 barbazquuxnarf

我发现解决这个问题的唯一方法是转向 Mock 文档中描述的模式,其中补丁程序在 TestCase< 的 setUp 方法中被实例化和启动 并在 tearDown 方法中停止。这符合我的目的,但增加了很多额外的样板文件并且不如类装饰器方法优雅。

还有其他方法可以解决这个问题吗?

最佳答案

1

假设你想在一个方法中临时恢复 foo.narffoo.narf 在装饰函数的上下文中是一个 MagicMock 对象。这个对象有一个 _mock_wraps 属性,当 mock 被调用时它会被调用!所以在你的模块的顶部,_narf = foo.narf,在你的测试用例中,foo.narf._mock_wraps = _narf

要注意的是,这只会传递给真正的函数,而不会实际将其交换回来,这意味着某些测试用例会失败(例如,如果它们依赖于实际上是“自身”的函数对象)。如果您的模拟具有其他属性,那可能会干扰(我没有测试太多),因为对 _mock_wraps() 的直通调用位于方法的底部,该方法首先考虑模拟的其他属性。

2

patch() 装饰器涉及将每个 patcher(每个方法的单独副本)添加到名为 patchings 的列表中,该列表是方法本身。 IE。您可以通过 self.test_foo.patchings 访问此列表,然后找到您想要的列表。

然而,当您使用 patch() 作为装饰器时,start()stop() 实际上并没有被调用,并且行为一旦你开始接触并改变它就会变得棘手。所以我写了这个上下文管理器。

class unpatch:
def __init__(self, name, method):
compare = patch(name)
self.patcher = next((
p for p in method.patchings
if p.target == compare.getter()
and p.attribute == compare.attribute
), None)
if self.patcher is None:
raise ValueError(name)

def __enter__(self):
self.patcher.__exit__()

def __exit__(self, *exc_info):
self.patcher.__enter__()

在您的测试用例中,您可以像这样使用它:

with unpatch('foo.narf', self.test_foo):
foo.narf()

免责声明:这是黑客行为。

关于Python:在模拟补丁类装饰器上调用停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25089752/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com