我有一个父对象,它接收一个连接对象。
我在此连接对象上运行方法以生成配置对象。当我嘲笑它时,我得到的不是Foo
:
<Mock name='mock().get_properties().property_c' id='1910891784064'>
代码:
# Real
class ClassC:
property_c = "Foo"
class ClassB:
def __init__(self):
pass
def login(self):
print("Logged in...")
def get_properties(self):
return ClassC()
class ClassA:
def __init__(self, conn):
self.conn = conn
self.conn.login()
a = ClassA(conn=ClassB()) >>> Logged in...
result = a.conn.get_properties()
print(result.property_c) >>> Foo
# Mocked
from unittest.mock import Mock
mock_b = Mock()
mock_c = Mock()
mock_c.property_c.return_value = "Foo_Mock"
mock_b.get_properties.return_value = mock_c
a = ClassA(conn=mock_b())
result = a.conn.get_properties()
print(result.property_c) >>> Output shown above
如何正确模拟呢?
mock_b.login.return_value = print("Logged in...")
awesoon的答案仍适用于此修改:
mock_b = Mock()
mock_c = Mock()
type(mock_c).property_c = PropertyMock(return_value="Foo_Mock")
mock_b.get_properties.return_value = mock_c
mock_b.login.return_value = print("Logged in...")
答案 0 :(得分:1)
您的代码中有两个问题:
在传递给mock_b
(ClassA
)时不要呼叫a = ClassA(conn=mock_b()
。调用模拟将创建另一个模拟,并且将不包含对mock_b
所做的更改。
使用PropertyMock
模仿属性:
type(mock_c).property_c = PropertyMock(return_value="Foo_Mock")
您也可以显式设置属性,但是PropertyMock
更为灵活。
最终代码是:
from unittest.mock import Mock, PropertyMock
mock_b = Mock()
mock_c = Mock()
type(mock_c).property_c = PropertyMock(return_value="Foo_Mock")
mock_b.get_properties.return_value = mock_c
print(mock_b.get_properties().property_c)
输出:
Foo_Mock
答案 1 :(得分:0)
我认为这行有问题:
a = ClassA(conn=mock_b())
您要在此处创建新的模拟。如果您尝试使用以下代码:
mock_b = Mock(name='mock_b')
a = ClassA(conn=mock_b())
print(mock_b)
print(a.conn)
您将看到,这是两个不同的模拟,具有不同的ID(例如):
<Mock name='mock_b' id='48709360'>
<Mock name='mock_b()' id='48709528'>
因此,所有的玻璃粉都需要用conn=mock_b()
代替conn=mock_b
。
如果您解决了该问题,则可以致电:
print(result.property_c()) # notice extra parathesis.
如果将get_property
方法添加到ClassC,然后模拟方法get_property,看起来会更好。