gpt4 book ai didi

python - 在 Python 中使用 '@patch.object' 和 'with patch.object' 有什么区别?

转载 作者:太空宇宙 更新时间:2023-11-03 11:23:05 29 4
gpt4 key购买 nike

在为我的应用程序编写单元测试时,我一直使用 @mock.patch@patch.object 装饰器。但是现在,当我使用装饰器进行一些单元测试时,我收到错误消息“TypeError: staticmethod object is not an iterator”。

但对于相同的代码,如果我使用 mock.patch.objectmock.patch.object,一切正常。

例如,在我的测试类中我有这个方法:

@staticmethod
def my_mock():
...do something

当我尝试下面的单元测试时

@mock.patch('mypackage.mymodule.my_method', side_effect=my_mock)
def test_something(self, my_method_mocked):
...test something

我收到“TypeError: staticmethod object is not an iterator”之前所述的错误消息。

但是当我尝试这种方式时

def test_something(self):
with patch.object(mymodule, "my_method") as mocked_method:
mocked_method.side_effect = self.my_mock
...test something

然后一切正常。

我已经阅读了有关模拟和单元测试的 Python 文档,但我找不到对这种行为的任何解释。

使用装饰器模式with模式有什么区别?我在哪里可以找到更多相关信息?

为了更清楚,这是我的代码结构:

class TestClass(unittest.TestCase):

@staticmethod
def my_mock():
...mock
return service

# doesn't work
@mock.patch('mypackage.mymodule.my_method', side_effect=my_mock)
def test_something(self, my_method_mocked):
...test something

# work
def test_something(self):
with patch.object(mymodule, "my_method") as mocked_method:
mocked_method.side_effect = self.my_mock
...test something

这就是为什么我不能执行 TestClass.my_mock 的原因。如果我这样做,我会得到一个引用错误。

最佳答案

您正在看到 Python 的描述符协议(protocol)的效果。区别不在于您如何调用 patch ,但在您分配给 side_effect 的值中每种情况下的属性。

class A(object):
@staticmethod
def my_mock():
pass

print type(my_mock) # As in your decorator case

# As in your context manager case
print type(A.my_mock)
print type(A().my_mock)

如果您运行这段代码,您会看到 print类声明中的语句输出 <type 'staticmethod'> ,因为您有对方法本身的引用。

另外两个print语句输出 <type 'function'>因为您没有对该方法的引用;你有一个方法的返回值的引用 __get__方法。这两个调用等同于

print type(A.__dict__['my_mock'].__get__(A))
print type(A.__dict__['my_mock'].__get__(A()))

参见 https://docs.python.org/2/howto/descriptor.html更全面地讨论如何使用描述符来实现三种类型的方法(静态、类和实例)。


真正的错误是因为patch期望一个可调用对象作为 side_effect 的值参数,如果失败,它需要一个可迭代的返回值。 staticmethod对象既不可调用也不可迭代。(试一试:A.__dict__['my_mock']()。)

为确保获得功能,您需要通过类访问该方法。

class Foo(object):
@staticmethod
def my_mock():
"whatever it does"

@mock.patch('mypackage.mymodule.my_method', side_effect=Foo.my_mock)
def test_something(self, my_method_mocked):
...test something

关于python - 在 Python 中使用 '@patch.object' 和 'with patch.object' 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38882187/

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