Как имитировать свойство с побочными эффектами на основе самого себя, используя PyTest

Я попробовал приведенный ниже код, используя new_callable=PropertyMock для имитации вызова свойства и autospec=True для доступа к себе в функции побочного эффекта:

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

Если это свойство, то вам все равно нужен autospec=True? Я думаю, что для методов важно гарантировать правильность используемой подписи.

Maxim Ivanov 06.05.2024 10:49

Обратите внимание, что этот вопрос является дубликатом вопроса Использование опции автоспецификации макета Mock.patch с пользовательским подклассом Mock

blhsing 06.05.2024 10:51

@blhsing Решение, приведенное в упомянутом вами сообщении, похоже, не работает с PropertyMock.

Guett31 06.05.2024 13:02
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
3
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку свойство some_property исправлено с помощью MagicMock, а затем исправлено с помощью 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

Другие вопросы по теме