繁体   English   中英

使用Mock()在Python中模拟嵌套对象

[英]Mock a nested object in Python using Mock()

我有一个父对象,它接收一个连接对象。

我在此连接对象上运行方法以生成配置对象。 当我嘲笑这个,而不是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

我该如何正确模拟呢?

Edit1-建议的重复SO答案仅部分回答了问题。

Edit2-我忘了包括模拟登录行为

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...")

您的代码中有两个问题:

  1. 传递给ClassAa = ClassA(conn=mock_b() )时不要调用mock_b ,调用一个模拟将创建另一个模拟,并且将不包含对mock_b所做的mock_b

  2. 使用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

我认为问题在于这条线:

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,则效果会更好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM