Подклассы MagicMock в питоне

У меня есть класс, который мне нужно патчить, который работает примерно так

class Foo(object):
    def __init__(self, query):
        self._query = query

    def do_stuff(self):
        # do stuff with self._query

Как бы я создал такой класс для Foo, чтобы

foo = MockFoo(query)
foo.do_stuff()

возвращает фиктивный результат, но все же с учетом данных, переданных для query, Я думал о подклассе MagicMock как это

class MockFoo(MagicMock):
    def __init__(self, query, *args, **kwargs):
        super(MagicMock, self).__init__(*args, **kwargs)
        self._query

    def do_stuff(self):
        mock_result = self._query * 10
        return MagicMock(return_value=mock_result)

но я не могу понять, как подать заявку patch использовать MockFoo вместо MagicMock в реальном TestCase. Мне нужно уметь написать тест, похожий на этот.

with patch('x.Foo') as mock_foo:
    # run test code
    self.assertTrue(mock_foo.called)
    self.assertEqual(mock_foo.wait.return_value, 20)

Я знаю, я могу просто использовать простой MagicMock с autospec=True или что-то и переопределить возвращаемые значения для каждого из методов, но было бы неплохо иметь фиктивный класс, который я могу просто использовать для замены производственного класса за один раз. Ключевым битом является необходимость доступа к переменной-члену self._query в имитирующих методах, при этом инициализируя его в конструкторе (как в производственном классе).

1 ответ

О вашей базовой вопрос ответ new_callable параметр в patch:

with patch('x.Foo', new_callable=MockFoo) as mock_foo:
    # run test code
    self.assertTrue(mock_foo.called)
    self.assertEqual(mock_foo.wait.return_value, 20)

Если вам нужно добавить аргумент MockFoo вызов init учитывает, что каждый аргумент не используется в patch будет вставлен в макет конструктора (MockFoo в твоем случае).

Если вам нужна оболочка вашего производственного класса, возможно, вы ищете не в том месте: макет - не оболочка.

Когда вы что-то издеваетесь, вы на самом деле не хотите знать, как работает ваш имитатор, а просто как его использует код и как ваш код реагирует на смоделированные объекты.

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