重用Mock来创建属性模块unittest.patch

时间:2016-09-12 12:00:09

标签: python unit-testing mocking python-unittest

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是什么? ______________

2 个答案:

答案 0 :(得分:3)

您将全班替换为您的补丁,而不是现有班级上的方法。 a = A()在替换类之前创建了A的实例,因此a.__class__仍引用实际的类,而不是模拟。

模拟只能一次替换一个引用,而不是引用的对象。在修补程序之前,名称A和属性a.__class__都是对类对象的引用。然后,您只修改了A引用,保留a.__class__

换句话说,a.__class__未修补,只有A,而A().b() 打印not working

您必须在课程上修补 方法,以便a.__class__仍引用Aa.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

不幸的是,您不能使用a.__class__修补Mock引用; Python只允许您使用该属性的实际类。

>>> 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

答案 1 :(得分:0)

您可能希望修补您的实例而不是您的课程:

with patch('__main__.a') as a_mock:
    a_mock.b.return_value = 'works perfectly ;)'
    print(a.b())