如何使用 PyTest 来模拟具有基于 self 的副作用的属性

问题描述 投票:0回答:1

我尝试了下面的代码,使用 new_callable=PropertyMock 来模拟属性调用,并使用 autospec=True 能够在副作用函数中访问 self :

from unittest.mock import PropertyMock

def some_property_mock(self):
    if self.__some_member == "some_value"
        return "some_different_value"
    else:
        return "some_other_value"

mocker.patch.object(
    SomeClass, "some_property", new_callable=PropertyMock, autospec=True, side_effect=some_property_mock)

它抛出以下异常: ValueError:无法同时使用“autospec”和“new_callable”

有什么替代方案可以实现预期的行为吗?

编辑: 我已经尝试过这篇文章中提供的解决方案https://stackoverflow.com/a/77940234/7217960,但它似乎不适用于PropertyMock。打印 结果 给出 MyMock name='my_property()' id='136687332325264' 而不是预期的 2

from unittest import mock

class MyClass(object):
    def __int__(self):
        self.my_attribute = 10

    @property
    def my_property(self):
        return self.my_attribute + 1
 
def unit_under_test():
    inst = MyClass()
    return inst.my_property
 
class MyMock(mock.PropertyMock):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print("MyMock __init__ called.")
 
with mock.patch.object(mock, 'MagicMock', MyMock):
    with mock.patch.object(MyClass, 'my_property', autospec=True, side_effect=lambda self: 2) as spy:
        result = unit_under_test()
        assert result == 2
        assert spy.call_count == 1
python mocking pytest
1个回答
0
投票

由于您想在调用时设置

MyMock
实例的返回值,因此您应该在使用
MagicMock
修补
MyMock
返回的模拟对象上执行此操作:

with mock.patch.object(mock, 'MagicMock', MyMock) as property_mock:
    with mock.patch.object(MyClass, 'my_property', autospec=True) as spy:
        property_mock.side_effect = lambda self: 2
        # or property_mock.return_value = 2
        result = unit_under_test()
        assert result == 2
        assert spy.call_count == 1

演示:https://ideone.com/rKo8mO

© www.soinside.com 2019 - 2024. All rights reserved.