【问题标题】:Python - Mocking an object's attribute with multiple values?Python - 用多个值模拟对象的属性?
【发布时间】:2015-10-11 22:49:41
【问题描述】:

我有一个改变对象属性的对象方法。另一种方法(我正在尝试测试的方法)多次调用第一种方法,然后使用已修改的属性。如何在明确说明第一种方法如何更改该属性的同时测试第二种方法?

例如:

def method_to_test(self):
    output = []
    for _ in range(5):
        self.other_method()
        output.append(self.attribute_changed_by_other_method)
    return output

我想指定attribute_changed_by_other_method 将由于other_method 而变成的一些特定值(而真正的other_method 使用概率来决定如何更改attribute_changed_by_other_method)。

我猜最好的方法是“模拟”属性attribute_changed_by_other_method,这样每次读取该值时,它都会返回我的规范的不同值。我似乎无法找到如何做到这一点。我看到的另一个选项是确保 other_method 被模拟以每次以定义的方式更新属性,但我不知道这样做的特别干净的方式。有人可以提出一种合理的解决方法吗?非常感谢。

【问题讨论】:

    标签: python unit-testing python-3.x testing mocking


    【解决方案1】:

    您实际上可以做的是将flexmock 用于other_method。你可以用 flexmock 做的是在你的类的实例上设置一个模拟。以下是如何使用它的示例:

    class MyTestClass(unittest.TestCase):
        def setUp(self):
            self.my_obj = MyClass()
            self.my_obj_mock = flexmock(self.my_obj)
    
        def my_test_case(self):
            self.my_obj_mock.should_receive('other_method').and_return(1).and_return(2).and_return(3)
            self.my_obj.method_to_test()
    

    所以,这里发生的情况是,在您的 MyClass 实例上,您正在从 self.my_obj 创建一个 flexmock 对象。然后在您的测试用例中,您声明当您调用method_to_test 时,您应该收到other_method,并且每次调用它都应该分别返回1, 2, 3

    另外,如果你还想知道如何模拟出attribute_changed_by_other_method,可以使用Mock的PropertyMock

    希望这会有所帮助。告诉我进展如何!

    【讨论】:

    • PropertyMock 为我找到了我想要的东西(使用您发布的链接中提供的 type() 方法)。
    【解决方案2】:

    对于仍在寻找直截了当答案的任何人,都可以使用PropertyMock 轻松完成,正如公认答案所暗示的那样。这是一种方法。

    from unittest.mock import patch, PropertyMock
    
    
    with patch("method_your_class_or_method_calls", new_callable=PropertyMock) as mock_call:
            mock_call.side_effect = [111, 222]
            class_or_method()
    

    对该修补方法的每次后续调用都会按顺序返回该列表。

    【讨论】:

      猜你喜欢
      • 2017-11-18
      • 2020-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-27
      • 2012-02-29
      • 1970-01-01
      相关资源
      最近更新 更多