Patch-исправление класса вводит дополнительный параметр?


Первый раз с использованием патча. Я пытался залатать один из моих классов для тестирования. Без патча попытка запуска проходит мимо определения тестовой функции, но с патчем определение тестовой функции, по-видимому, требует другого параметра, и я получаю

TypeError: testAddChannelWithNamePutsChannel() takes exactly 1 argument (2 given)

Ошибка. Тестовый код выглядит следующим образом:

import unittest
import mock
from notification.models import Channel, addChannelWithName, deleteChannelWithName

class TestChannel(unittest.TestCase):
    @mock.patch('notification.models.Channel')
    def testAddChannelWithNamePutsChannel(self):
        addChannelWithName('channel1')
        Channel.put.assert_called_with()

Почему он требует дополнительного параметра с патчем и каким должен быть этот параметр? Большое вам спасибо!

2 13

2 ответа:

Patch передает экземпляр объекта patched вашему методу тестирования (или каждому методу тестирования, если выполняется исправление на уровне класса). Это удобно, потому что позволяет задать возвращаемые значения и побочные эффекты, или проверить сделанные вызовы

from unittest.mock import patch

@patch('some_module.sys.stdout')
def test_something_with_a_patch(self, mock_sys_stdout):
    mock_sys_stdout.return_value = 'My return value from stdout'

    my_function_under_test()

    self.assertTrue(mock_sys_stdout.called)
    self.assertEqual(output, mock_sys_stdout.return_value)

Если вы просто хотите буквально залатать что-то, чтобы игнорировать его, то вы можете вызвать patch следующим вызовом

from unittest.mock import patch, Mock

@patch('some_module.sys.stdout', Mock())
def test_something_with_a_patch(self):

, который заменяет sys.stdout в some_module на объект Mock и не передает его в метод.

patch передает исправленный объект в тестовую функцию. Его документально здесь:

Патч как декоратор функций, создающий макет для вас и передающий его в украшенную функцию:

>>>
>>> @patch('__main__.SomeClass')
... def function(normal_argument, mock_class):
...     print(mock_class is SomeClass)
...
>>> function(None)
True