Как насмехаться с базовым классом с помощью макетной библиотеки python

Я пытаюсь использовать mock для написания некоторых модульных тестов в python.

Например, у меня есть следующий класс:

  • Как мне высмеять обработчик сигнала django?
  • Как высмеять метод SendGrid в Python
  • Издевательствовать только один метод на объекте
  • Использование unittest.mock для исправления ввода () в Python 3
  • Модуль тестирования приложения python, использующего библиотеку запросов
  • Могу ли я «подделать» пакет (или хотя бы модуль) в python для тестирования?
  •  class TCPHandler(socketserver.BaseRequestHandler): def handle(self): self.data = self.request.recv(1024).strip() 

    И я хочу проверить метод handle . Без необходимости принимать что-либо о socketserver.BaseRequestHandler . Например, я хочу утверждать, что handle вызывает recv с аргументом 1024 . Можно ли это сделать с макетом? Т.е. заменить базовый класс socketserver.BaseRequestHandler на mock? Или я с этим согласен?


    С ответом ecatmur (спасибо!) Я сначала попробовал следующее:

     patcher = patch.object(TCPHandler, '__bases__', (Mock,)) with patcher: patcher.is_local = True handler = TCPHandler() handler.handle() 

    Но теперь handle не называется anylonger и dir(handler) дает:

     ['assert_any_call', 'assert_called_once_with', 'assert_called_with', 'assert_has_calls', 'attach_mock', 'call_args', 'call_args_list', 'call_count', 'called', 'configure_mock', 'method_calls', 'mock_add_spec', 'mock_calls', 'reset_mock', 'return_value', 'side_effect'] 

    type(handler) дает <class 'mock.TCPHandler'>

    Который я интерпретирую, что исправление базового класса также превращает мой производный класс в макет.


    Я попробовал еще одну идею:

     mock = MagicMock() TCPHandler.handle(mock) #assertions 

    Однако, как кажется, не следует называть насмешку.

  • python dataframe pandas drop column, используя int
  • как я позиционирую кнопки в tkinter?
  • питонный кортеж
  • Обработка и работа с двоичными данными HEX с помощью python
  • Ускорить запись в файлы
  • Ошибка использования FigureCanvasQTAgg в MatplotlibWidget pyqt5
  • 3 Solutions collect form web for “Как насмехаться с базовым классом с помощью макетной библиотеки python”

    Вы можете сделать это, __bases__ производного класса:

     def test_derived(): patcher = mock.patch.object(Derived, '__bases__', (mock.Mock,)) with patcher: patcher.is_local = True d = Derived() print d.foo() 

    is_local необходимо остановить mock.patch от попытки вызвать delattr при изменении патча.

    Я думаю, проблема в том, что вы пытаетесь высмеять фактический код, который хотите проверить. Вместо объектов, вызываемых этим кодом. Если вам интересно узнать, вызывает ли метод дескриптора метод recv на self.request, тогда вытереть метод recv.

     def test_tcp_handler_method(self): handler = TCPHandler() handler.request = Mock() handler.handle() self.assertTrue(handler.request.recv.called) self.assertEqual(handler.request.recv.call_args[0], 1024) 

    Возможно, вам придется выполнить дополнительную настройку, чтобы получить обработчик для создания экземпляра, но основная идея должна быть ясной.

    Я не знаю, является ли это лучшим решением, но мне удалось переопределить предыдущий класс с помощью другого родителя, использующего type () . Я создал функцию patch_parent() , которая возвращает класс с родительским макетом:

     from contextlib import contextmanager @contextmanager def patch_parent(class_): """ Mock the bases """ yield type(class_.__name__, (Mock,), dict(class_.__dict__)) 

    После этого вы можете использовать patch_parent следующим образом:

     class Bar(): def method(self, param1, param2...): ... class Foo(Bar): pass >>> with patch_parent(Foo) as MockFoo: ... f = MockFoo() ... print f ... print f.method() ... <Foo id='15488016'> <Foo name='mock.method()' id='15541520'> >>> s = Foo() >>> s.method() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: method() takes exactly 3 arguments (1 given) 

    Класс MockFoo прежнему имеет методы класса Foo и не имеет методов, определенных в родительском, поскольку родительский класс теперь является классом Mock .

    Python - лучший язык программирования в мире.