模拟Python类的方法和属性的子集

费利佩·费里

我正在使用mockPython模块执行测试。

有时候我在模拟一个类,但是我只想模拟它的一些方法和属性,而不是全部。

假设以下情况:

# module.py
class SomeClass:
    def some_method(self):
        return 100

    def another_method(self):
        return 500

# test.py
class Tests(unittest.TestCase):
    @patch('module.SomeClass')
    def test_some_operation(self, some_class_mock):
        some_class_instance = some_class_mock.return_value

        # I'm mocking only the some_method method.
        some_class_instance.some_method.return_value = 25

        # This is ok, the specific method I mocked returns the value I wished.
        self.assertEquals(
            25,
            SomeClass().some_method()
        )

        # However, another_method, which I didn't mock, returns a MagicMock instance
        # instead of the original value 500
        self.assertEquals(
            500,
            SomeClass().another_method()
        )

在上面的代码中,一旦我修补了SomeClass类,对未明确设置return_values的方法的调用将返回MagicMock对象。

我的问题是:我该如何仅模拟某些类方法而又不破坏其他类的方法?

我可以想到两种方法,但没有一种是真正好的。

  1. 一种方法是将模拟方法设置为原始类方法,如下所示:

    some_class_instance.another_method = SomeClass.another_method
    

    这并不是真正希望的,因为该类可能具有许多“取消模拟”的方法和属性。

  2. 另一种方法是显式修补我想要的每个方法,例如:

     @patch('module.SomeClass.some_method')
     def test_some_operation(self, some_method_mock):
    

    但是,如果我想模拟类本身(例如,模拟对初始化程序的调用),这实际上是行不通的。SomeClass无论如何,以下代码将覆盖all的方法。

     @patch('module.SomeClass.some_method')
     @patch('module.SomeClass')
     def test_some_operation(self, some_class_mock, some_method_mock):
    

这是一个更具体的示例:

class Order:
    def process_event(self, event, data):
        if event == 'event_a':
            return self.process_event_a(data)

        elif event == 'event_b':
            return self.process_event_b(data)

        else:
            return None

    def process_event_a(self, data):
        # do something with data

    def process_event_b(self, data):
        # do something different with data

在这种情况下,我有一个通用方法process_event,该方法根据提供的事件调用特定的处理事件。

我只想测试该方法process_event我只想知道是否根据我提供的事件调用了适当的特定事件。

因此,在我的测试案例中,我想做的是模拟justprocess_event_aprocess_event_bprocess_event使用特定参数调用原始对象,然后断言其中一个process_event_aprocess_event_b使用适当的参数进行调用。

Amir Afianian |

不必修补整个类,而必须修补对象。即,创建您的类的实例,然后修补该实例的方法。

请注意,您也可以使用装饰器@patch.object代替我的方法。

class SomeClass:
    def some_method(self):
        return 100

    def another_method(self):
        return 500

在你的 test.py

from unittest import mock

class Tests(unittest.TestCase):
    

    def test_some_operation(self):
        some_class_instance = SomeClass()

        # I'm mocking only the some_method method.
        with mock.patch.object(some_class_instance, 'some_method', return_value=25) as cm:

            # This is gonna be ok
            self.assertEquals(
                25,
                SomeClass().some_method()
            )

            # The other methods work as they were supposed to.
            self.assertEquals(
                500,
                SomeClass().another_method()
            )

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章