重用 Mock 创建属性模拟 unittest.patch
Reusing Mock to create attribute mocks unittest.patch
from unittest.mock import patch
class A:
def b(self):
return 'HAHAHA A'
a = A()
with patch('__main__.A') as a_mock:
a_mock.b.return_value = 'not working'
print(a.b())
HAHAHA A
>>>
为什么不打印 'not working'
?那么 a_mock 是干什么用的呢? ______________
您用补丁替换了 整个 class,而不是现有 class 上的方法。 a = A()
在替换 class 之前创建了 A
的实例,因此 a.__class__
仍然引用实际的 class,而不是模拟。
Mocking 一次只能替换一个引用,而不能替换引用的对象。在补丁之前,名称 A
和属性 a.__class__
都是对 class 对象的引用。然后,您只修补了 A
引用,将 a.__class__
留在原地。
换句话说,a.__class__
没有打补丁,只有A
,A().b()
会打印not working
。
您必须修补只是 class 上的方法,这样a.__class__
仍然引用A
,并且a.b
将解析为修补后的 A.b
mock:
with patch('__main__.A.b') as b_mock:
b_mock.return_value = 'working as long as you patch the right object'
print(a.b())
演示:
>>> with patch('__main__.A.b') as b_mock:
... b_mock.return_value = 'working as long as you patch the right object'
... print(a.b())
...
working as long as you patch the right object
不幸的是,您不能用 Mock
修补 a.__class__
引用; Python 只允许您对该属性使用实际的 classes。
>>> with patch('__main__.a.__class__') as a_class_mock:
... a_class_mock.b.return_value = 'working as long as you patch the right object'
... print(a.b())
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.5/unittest/mock.py", line 1312, in __enter__
setattr(self.target, self.attribute, new_attr)
TypeError: __class__ must be set to a class, not 'MagicMock' object
您可能想要修补您的实例而不是您的 class:
with patch('__main__.a') as a_mock:
a_mock.b.return_value = 'works perfectly ;)'
print(a.b())
from unittest.mock import patch
class A:
def b(self):
return 'HAHAHA A'
a = A()
with patch('__main__.A') as a_mock:
a_mock.b.return_value = 'not working'
print(a.b())
HAHAHA A
>>>
为什么不打印 'not working'
?那么 a_mock 是干什么用的呢? ______________
您用补丁替换了 整个 class,而不是现有 class 上的方法。 a = A()
在替换 class 之前创建了 A
的实例,因此 a.__class__
仍然引用实际的 class,而不是模拟。
Mocking 一次只能替换一个引用,而不能替换引用的对象。在补丁之前,名称 A
和属性 a.__class__
都是对 class 对象的引用。然后,您只修补了 A
引用,将 a.__class__
留在原地。
换句话说,a.__class__
没有打补丁,只有A
,A().b()
会打印not working
。
您必须修补只是 class 上的方法,这样a.__class__
仍然引用A
,并且a.b
将解析为修补后的 A.b
mock:
with patch('__main__.A.b') as b_mock:
b_mock.return_value = 'working as long as you patch the right object'
print(a.b())
演示:
>>> with patch('__main__.A.b') as b_mock:
... b_mock.return_value = 'working as long as you patch the right object'
... print(a.b())
...
working as long as you patch the right object
不幸的是,您不能用 Mock
修补 a.__class__
引用; Python 只允许您对该属性使用实际的 classes。
>>> with patch('__main__.a.__class__') as a_class_mock:
... a_class_mock.b.return_value = 'working as long as you patch the right object'
... print(a.b())
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.5/unittest/mock.py", line 1312, in __enter__
setattr(self.target, self.attribute, new_attr)
TypeError: __class__ must be set to a class, not 'MagicMock' object
您可能想要修补您的实例而不是您的 class:
with patch('__main__.a') as a_mock:
a_mock.b.return_value = 'works perfectly ;)'
print(a.b())