Документация Python неофициальный перевод

unittest.mock.md

1849 строк · 116.5 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.3/library/unittest.mock.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 26.4. [`unittest.mock`](https://python-all.ru/3.3/library/unittest.mock.html#module-unittest.mock) – библиотека mock-объектов89Новое в версии 3.3.1011[`unittest.mock`](https://python-all.ru/3.3/library/unittest.mock.html#module-unittest.mock) – библиотека для тестирования в Python. С её помощью можно заменять части тестируемой системы mock-объектами и проверять, как они использовались.1213*unittest.mock* предоставляет основной класс [`Mock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock), устраняющий необходимость создавать множество заглушек в тестовом наборе. После выполнения действия можно проверять, какие методы/атрибуты использовались и с какими аргументами они вызывались. Также можно задавать возвращаемые значения и устанавливать нужные атрибуты обычным способом.1415Кроме того, mock предоставляет декоратор [`patch()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.patch), который подменяет атрибуты модулей и классов в пределах теста, а также [`sentinel`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.sentinel) для создания уникальных объектов. Примеры использования [https://python-all.ru/3.3/library/unittest.mock.html#quick-guide](https://python-all.ru/3.3/library/unittest.mock.html#quick-guide), и см. в кратком руководстве.1617Mock очень прост в использовании и предназначен для работы с [`unittest`](https://python-all.ru/3.3/library/unittest.html#module-unittest). Mock основан на шаблоне «действие -\> проверка», а не на *«запись -\> воспроизведение»*, используемом многими фреймворками для моков.1819Существует обратный порт *unittest.mock* для более старых версий Python, доступный как [mock на PyPI](https://python-all.ru/3.3/library/unittest.mock.html).2021**Исходный код:** [Lib/unittest/mock.py](https://python-all.ru/src/3.3/Lib/unittest/mock.py)2223## 26.4.1. Краткое руководство2425Объекты [`Mock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock) и [`MagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.MagicMock) создают все атрибуты и методы по мере обращения к ним и запоминают подробности их использования. Можно настраивать их, задавая возвращаемые значения или ограничивая доступные атрибуты, а затем проверять, как они использовались:2627```python28>>> from unittest.mock import MagicMock29>>> thing = ProductionClass()30>>> thing.method = MagicMock(return_value=3)31>>> thing.method(3, 4, 5, key='value')32333>>> thing.method.assert_called_with(3, 4, 5, key='value')34```3536`side_effect` позволяет выполнять побочные действия, в том числе вызывать исключение при вызове mock-объекта:3738```python39>>> mock = Mock(side_effect=KeyError('foo'))40>>> mock()41Traceback (most recent call last):42 ...43KeyError: 'foo'44```4546```python47>>> values = {'a': 1, 'b': 2, 'c': 3}48>>> def side_effect(arg):49...     return values[arg]50...51>>> mock.side_effect = side_effect52>>> mock('a'), mock('b'), mock('c')53(1, 2, 3)54>>> mock.side_effect = [5, 4, 3, 2, 1]55>>> mock(), mock(), mock()56(5, 4, 3)57```5859Mock имеет много других способов настройки и управления его поведением. Например, аргумент *spec* настраивает mock на использование спецификации другого объекта. Попытка доступа к атрибутам или методам mock, которых нет в спецификации, приведет к *AttributeError*.6061Декоратор/менеджер контекста [`patch()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.patch) упрощает подмену классов или объектов в тестируемом модуле. Указанный объект заменяется mock-объектом (или другим объектом) на время теста и восстанавливается после его завершения:6263```python64>>> from unittest.mock import patch65>>> @patch('module.ClassName2')66... @patch('module.ClassName1')67... def test(MockClass1, MockClass2):68...     module.ClassName1()69...     module.ClassName2()70...     assert MockClass1 is module.ClassName171...     assert MockClass2 is module.ClassName272...     assert MockClass1.called73...     assert MockClass2.called74...75>>> test()76```7778> **Примечание**79>80> При вложении декораторов patch моки передаются в декорируемую функцию в том же порядке, в котором они применяются (обычный *python*-порядок применения декораторов). То есть снизу вверх, поэтому в примере выше mock для *module.ClassName1* передаётся первым.81>82> При использовании *patch* важно патчить объекты в том пространстве имён, где они ищутся. Обычно это очевидно, но для быстрого ознакомления прочитайте [*где патчить*](https://python-all.ru/3.3/library/unittest.mock.html#where-to-patch).8384Помимо декоратора, *patch* можно использовать как менеджер контекста в операторе with:8586```python87>>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method:88...     thing = ProductionClass()89...     thing.method(1, 2, 3)90...91>>> mock_method.assert_called_once_with(1, 2, 3)92```9394Существует также [`patch.dict()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.patch.dict) для установки значений в словаре только в пределах области видимости с последующим восстановлением исходного состояния словаря после завершения теста:9596```python97>>> foo = {'key': 'value'}98>>> original = foo.copy()99>>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True):100...     assert foo == {'newkey': 'newvalue'}101...102>>> assert foo == original103```104105Mock поддерживает имитацию [*магических методов*](https://python-all.ru/3.3/library/unittest.mock.html#magic-methods) Python. Самый простой способ использования магических методов – класс [`MagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.MagicMock). Он позволяет делать, например, следующее:106107```python108>>> mock = MagicMock()109>>> mock.__str__.return_value = 'foobarbaz'110>>> str(mock)111'foobarbaz'112>>> mock.__str__.assert_called_with()113```114115Mock позволяет назначать функции (или другие экземпляры Mock) магическим методам, и они будут вызываться соответствующим образом. Класс *MagicMock* – это просто вариант Mock, у которого все магические методы уже предсозданы (ну, по крайней мере все полезные).116117Далее приведён пример использования магических методов с обычным классом Mock:118119```python120>>> mock = Mock()121>>> mock.__str__ = Mock(return_value='wheeeeee')122>>> str(mock)123'wheeeeee'124```125126Чтобы mock-объекты в тестах имели тот же API, что и заменяемые объекты, можно использовать [*автоспецификацию*](https://python-all.ru/3.3/library/unittest.mock.html#auto-speccing). Автоспецификацию можно задать через аргумент *autospec* у patch или с помощью функции [`create_autospec()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.create_autospec). Автоспецификация создаёт mock-объекты, имеющие те же атрибуты и методы, что и заменяемые объекты, а любые функции и методы (включая конструкторы) имеют ту же сигнатуру вызова, что и реальный объект.127128Благодаря этому заглушки будут вести себя так же, как рабочий код, если их использовать неправильно:129130```python131>>> from unittest.mock import create_autospec132>>> def function(a, b, c):133...     pass134...135>>> mock_function = create_autospec(function, return_value='fishy')136>>> mock_function(1, 2, 3)137'fishy'138>>> mock_function.assert_called_once_with(1, 2, 3)139>>> mock_function('wrong arguments')140Traceback (most recent call last):141 ...142TypeError: <lambda>() takes exactly 3 arguments (1 given)143```144145*create\_autospec* также можно использовать с классами – в этом случае он копирует сигнатуру метода *\_\_init\_\_*, а с вызываемыми объектами – сигнатуру метода *\_\_call\_\_*.146147## 26.4.2. Класс Mock148149*Mock* – это гибкий mock-объект, предназначенный для замены заглушек и тестовых дублёров в вашем коде. Моки вызываемы и при обращении к ним создают атрибуты как новые моки [\[1\]](https://python-all.ru/3.3/library/unittest.mock.html#id3). Обращение к одному и тому же атрибуту всегда возвращает один и тот же mock. Моки записывают, как вы их используете, позволяя проверять, что ваш код с ними сделал.150151[`MagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.MagicMock) – это подкласс *Mock* со всеми предсозданными и готовыми к использованию магическими методами. Существуют также невызываемые варианты, полезные при имитации объектов, которые не являются вызываемыми: [`NonCallableMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.NonCallableMock) и [`NonCallableMagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.NonCallableMagicMock)152153Декоратор [`patch()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.patch) упрощает временную замену классов в определённом модуле объектом *Mock*. По умолчанию *patch* создаёт *MagicMock*. Можно указать альтернативный класс *Mock* с помощью аргумента *new\_callable* для *patch*.154155#### `class unittest.mock.Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, **kwargs)`156157Создаёт новый объект *Mock*. *Mock* принимает несколько необязательных аргументов, задающих поведение объекта Mock:158159- *spec*: Это может быть либо список строк, либо существующий объект (класс или экземпляр), который служит спецификацией для mock-объекта. Если передать объект, то список строк формируется вызовом dir для этого объекта (за исключением неподдерживаемых магических атрибутов и методов). Доступ к любому атрибуту, не входящему в этот список, приведёт к *AttributeError*.160161  Если *spec* является объектом (а не списком строк), то [`__class__`](https://python-all.ru/3.3/library/stdtypes.html#instance.__class__) возвращает класс объекта спецификации. Это позволяет мокам проходить проверки *isinstance*.162- *spec\_set*: Более строгий вариант *spec*. При его использовании попытка *установить* или получить атрибут mock, которого нет в объекте, переданном как *spec\_set*, приведёт к *AttributeError*.163- *side\_effect*: функция, вызываемая при каждом вызове Mock. См. атрибут [`side_effect`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.side_effect). Полезен для генерации исключений или динамического изменения возвращаемых значений. Функция вызывается с теми же аргументами, что и mock, и если она не возвращает [`DEFAULT`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.DEFAULT), то возвращаемое значение этой функции используется как возвращаемое значение.164165  Альтернативно *side\_effect* может быть классом исключения или экземпляром. В этом случае исключение будет возбуждено при вызове заглушки.166167  Если *side\_effect* является итерируемым, то каждый вызов заглушки будет возвращать следующее значение из итерируемого.168169  *side\_effect* можно сбросить, установив его в *None*.170- *return\_value*: значение, возвращаемое при вызове mock-объекта. По умолчанию это новый Mock (создаётся при первом обращении). См. атрибут [`return_value`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.return_value).171- *wraps*: Объект, который будет обёрнут mock-объектом. Если *wraps* не равен None, то вызов Mock передаёт вызов обёрнутому объекту (возвращая реальный результат). Доступ к атрибуту mock возвращает объект Mock, который обёртывает соответствующий атрибут обёрнутого объекта (поэтому попытка доступа к несуществующему атрибуту вызовет *AttributeError*).172173  Если для заглушки явно задан *return\_value*, то вызовы не передаются обёрнутому объекту, а возвращается значение *return\_value*.174- *name*: если у заглушки есть имя, оно будет использоваться в repr заглушки. Это может быть полезно для отладки. Имя распространяется на дочерние заглушки.175176Mock-объекты также можно вызывать с произвольными именованными аргументами. Они будут использованы для установки атрибутов mock'а после его создания. Подробнее см. метод [`configure_mock()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.configure_mock).177178#### `assert_called_with(*args, **kwargs)`179180Этот метод – удобный способ проверить, что вызовы сделаны определённым образом:181182```python183>>> mock = Mock()184>>> mock.method(1, 2, 3, test='wow')185<Mock name='mock.method()' id='...'>186>>> mock.method.assert_called_with(1, 2, 3, test='wow')187```188189#### `assert_called_once_with(*args, **kwargs)`190191Утверждает, что mock был вызван ровно один раз и с указанными аргументами.192193```python194>>> mock = Mock(return_value=None)195>>> mock('foo', bar='baz')196>>> mock.assert_called_once_with('foo', bar='baz')197>>> mock('foo', bar='baz')198>>> mock.assert_called_once_with('foo', bar='baz')199Traceback (most recent call last):200  ...201AssertionError: Expected 'mock' to be called once. Called 2 times.202```203204#### `assert_any_call(*args, **kwargs)`205206Утверждает, что заглушка вызывалась с указанными аргументами.207208Утверждение проходит, если mock *когда-либо* был вызван, в отличие от [`assert_called_with()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.assert_called_with) и [`assert_called_once_with()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.assert_called_once_with), которые проходят только в том случае, если вызов был последним.209210```python211>>> mock = Mock(return_value=None)212>>> mock(1, 2, arg='thing')213>>> mock('some', 'thing', 'else')214>>> mock.assert_any_call(1, 2, arg='thing')215```216217#### `assert_has_calls(calls, any_order=False)`218219Проверяет, что mock был вызван с указанными вызовами. Проверяется список *mock\_calls*.220221Если *any\_order* равно false (значение по умолчанию), то вызовы должны быть последовательными. Допускаются дополнительные вызовы до или после указанных вызовов.222223Если *any\_order* равен true, то вызовы могут быть в любом порядке, но все они должны присутствовать в [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls).224225```python226>>> mock = Mock(return_value=None)227>>> mock(1)228>>> mock(2)229>>> mock(3)230>>> mock(4)231>>> calls = [call(2), call(3)]232>>> mock.assert_has_calls(calls)233>>> calls = [call(4), call(2), call(3)]234>>> mock.assert_has_calls(calls, any_order=True)235```236237#### `reset_mock()`238239Метод reset\_mock сбрасывает все атрибуты вызовов у макета:240241```python242>>> mock = Mock(return_value=None)243>>> mock('hello')244>>> mock.called245True246>>> mock.reset_mock()247>>> mock.called248False249```250251Это может быть полезно, когда нужно выполнить серию проверок, используя один и тот же объект. Обратите внимание: *reset\_mock* *не* очищает возвращаемое значение, [`side_effect`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.side_effect) или любые дочерние атрибуты, установленные обычным присваиванием. Дочерние моки и mock возвращаемого значения (если есть) также сбрасываются.252253#### `mock_add_spec(spec, spec_set=False)`254255Добавляет спецификацию к макету. *spec* может быть объектом или списком строк. Только атрибуты, указанные в *spec*, можно получить как атрибуты макета.256257Если *spec\_set* равен *True*, то можно устанавливать только атрибуты, входящие в спецификацию.258259#### `attach_mock(mock, attribute)`260261Присоединяет mock в качестве атрибута данного mock'а, заменяя его имя и родителя. Вызовы присоединённого mock'а будут записываться в атрибутах [`method_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.method_calls) и [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls) данного объекта.262263#### `configure_mock(**kwargs)`264265Устанавливает атрибуты макета через именованные аргументы.266267Атрибуты, возвращаемые значения и побочные эффекты могут быть установлены на дочерних макетах с помощью стандартной точечной нотации и распаковки словаря в вызове метода:268269```python270>>> mock = Mock()271>>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}272>>> mock.configure_mock(**attrs)273>>> mock.method()2743275>>> mock.other()276Traceback (most recent call last):277  ...278KeyError279```280281То же самое можно сделать в вызове конструктора макетов:282283```python284>>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}285>>> mock = Mock(some_attribute='eggs', **attrs)286>>> mock.some_attribute287'eggs'288>>> mock.method()2893290>>> mock.other()291Traceback (most recent call last):292  ...293KeyError294```295296*configure\_mock* существует для упрощения настройки после создания mock.297298#### `__dir__()`299300Объекты *Mock* ограничивают результаты *dir(some\_mock)* только полезными результатами. Для моков с *spec* это включает все разрешённые атрибуты для этого мока.301302См. [`FILTER_DIR`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.FILTER_DIR), чтобы узнать, что делает эта фильтрация и как её отключить.303304#### `_get_child_mock(**kw)`305306Создаёт дочерние макеты для атрибутов и возвращаемого значения. По умолчанию дочерние макеты будут того же типа, что и родительский. Подклассы Mock могут переопределить это для настройки способа создания дочерних макетов.307308Для невызываемых макетов будет использоваться вызываемый вариант (а не пользовательский подкласс).309310#### `called`311312Логическое значение, указывающее, был ли вызван mock-объект:313314```python315>>> mock = Mock(return_value=None)316>>> mock.called317False318>>> mock()319>>> mock.called320True321```322323#### `call_count`324325Целое число, показывающее, сколько раз был вызван mock-объект:326327```python328>>> mock = Mock(return_value=None)329>>> mock.call_count3300331>>> mock()332>>> mock()333>>> mock.call_count3342335```336337#### `return_value`338339Установите это, чтобы настроить значение, возвращаемое при вызове mock:340341```python342>>> mock = Mock()343>>> mock.return_value = 'fish'344>>> mock()345'fish'346```347348Значение по умолчанию – это mock-объект, и его можно настроить обычным способом:349350```python351>>> mock = Mock()352>>> mock.return_value.attribute = sentinel.Attribute353>>> mock.return_value()354<Mock name='mock()()' id='...'>355>>> mock.return_value.assert_called_with()356```357358*return\_value* также можно задать в конструкторе:359360```python361>>> mock = Mock(return_value=3)362>>> mock.return_value3633364>>> mock()3653366```367368#### `side_effect`369370Это может быть либо функция, вызываемая при вызове мока, либо исключение (класс или экземпляр), которое будет возбуждено.371372Если передать функцию, она будет вызвана с теми же аргументами, что и mock, и если функция не вернёт синглтон [`DEFAULT`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.DEFAULT), то вызов mock'а вернёт то, что вернула функция. Если функция возвращает [`DEFAULT`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.DEFAULT), то mock вернёт своё обычное значение (из [`return_value`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.return_value)).373374Пример mock-объекта, возбуждающего исключение (для проверки обработки исключений API):375376```python377>>> mock = Mock()378>>> mock.side_effect = Exception('Boom!')379>>> mock()380Traceback (most recent call last):381  ...382Exception: Boom!383```384385Использование *side\_effect* для возврата последовательности значений:386387```python388>>> mock = Mock()389>>> mock.side_effect = [3, 2, 1]390>>> mock(), mock(), mock()391(3, 2, 1)392```393394Функция *side\_effect* вызывается с теми же аргументами, что и мок (поэтому разумно, чтобы она принимала произвольные позиционные и ключевые аргументы), и то, что она возвращает, используется как возвращаемое значение вызова. Исключение составляет случай, когда *side\_effect* возвращает [`DEFAULT`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.DEFAULT), – тогда используется обычное [`return_value`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.return_value).395396```python397>>> mock = Mock(return_value=3)398>>> def side_effect(*args, **kwargs):399...     return DEFAULT400...401>>> mock.side_effect = side_effect402>>> mock()4033404```405406*side\_effect* можно задать в конструкторе. Ниже пример, который прибавляет единицу к значению, с которым был вызван мок, и возвращает его:407408```python409>>> side_effect = lambda value: value + 1410>>> mock = Mock(side_effect=side_effect)411>>> mock(3)4124413>>> mock(-8)414-7415```416417Установка *side\_effect* в *None* очищает его:418419```python420>>> m = Mock(side_effect=KeyError, return_value=3)421>>> m()422Traceback (most recent call last):423 ...424KeyError425>>> m.side_effect = None426>>> m()4273428```429430#### `call_args`431432Это либо *None* (если мок ещё не вызывался), либо аргументы, с которыми мок был вызван в последний раз. Значение будет представлять собой кортеж: первый элемент – это позиционные аргументы, с которыми был вызван мок (или пустой кортеж), а второй элемент – ключевые аргументы (или пустой словарь).433434```python435>>> mock = Mock(return_value=None)436>>> print mock.call_args437None438>>> mock()439>>> mock.call_args440call()441>>> mock.call_args == ()442True443>>> mock(3, 4)444>>> mock.call_args445call(3, 4)446>>> mock.call_args == ((3, 4),)447True448>>> mock(3, 4, 5, key='fish', next='w00t!')449>>> mock.call_args450call(3, 4, 5, key='fish', next='w00t!')451```452453*call\_args*, а также элементы списков [`call_args_list`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args_list), [`method_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.method_calls) и [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls) являются объектами [`call`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.call). Это кортежи, поэтому их можно распаковать, чтобы получить отдельные аргументы и составлять более сложные утверждения. См. [*вызовы как кортежи*](https://python-all.ru/3.3/library/unittest.mock.html#calls-as-tuples).454455#### `call_args_list`456457Это список всех вызовов, сделанных к объекту-моку, в порядке их выполнения (поэтому длина списка равна количеству вызовов). До того, как были сделаны какие-либо вызовы, он представляет собой пустой список. Объект [`call`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.call) можно использовать для удобного построения списков вызовов для сравнения с *call\_args\_list*.458459```python460>>> mock = Mock(return_value=None)461>>> mock()462>>> mock(3, 4)463>>> mock(key='fish', next='w00t!')464>>> mock.call_args_list465[call(), call(3, 4), call(key='fish', next='w00t!')]466>>> expected = [(), ((3, 4),), ({'key': 'fish', 'next': 'w00t!'},)]467>>> mock.call_args_list == expected468True469```470471Элементами *call\_args\_list* являются объекты [`call`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.call). Их можно распаковать как кортежи, чтобы получить отдельные аргументы. См. [*вызовы как кортежи*](https://python-all.ru/3.3/library/unittest.mock.html#calls-as-tuples).472473#### `method_calls`474475Помимо отслеживания собственных вызовов, mock-объекты также отслеживают вызовы методов и атрибутов, а также *их* методов и атрибутов:476477```python478>>> mock = Mock()479>>> mock.method()480<Mock name='mock.method()' id='...'>481>>> mock.property.method.attribute()482<Mock name='mock.property.method.attribute()' id='...'>483>>> mock.method_calls484[call.method(), call.property.method.attribute()]485```486487Элементами *method\_calls* являются объекты [`call`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.call). Их можно распаковать как кортежи, чтобы получить отдельные аргументы. См. [*вызовы как кортежи*](https://python-all.ru/3.3/library/unittest.mock.html#calls-as-tuples).488489#### `mock_calls`490491*mock\_calls* записывает *все* вызовы объекта-мока, его методов, магических методов *и* моков возвращаемого значения.492493```python494>>> mock = MagicMock()495>>> result = mock(1, 2, 3)496>>> mock.first(a=3)497<MagicMock name='mock.first()' id='...'>498>>> mock.second()499<MagicMock name='mock.second()' id='...'>500>>> int(mock)5011502>>> result(1)503<MagicMock name='mock()()' id='...'>504>>> expected = [call(1, 2, 3), call.first(a=3), call.second(),505... call.__int__(), call()(1)]506>>> mock.mock_calls == expected507True508```509510Элементами *mock\_calls* являются объекты [`call`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.call). Их можно распаковать как кортежи, чтобы получить отдельные аргументы. См. [*вызовы как кортежи*](https://python-all.ru/3.3/library/unittest.mock.html#calls-as-tuples).511512#### `__class__`513514Обычно атрибут *\_\_class\_\_* объекта возвращает его тип. Для объекта-мока с *spec* *\_\_class\_\_* возвращает класс спецификации вместо этого. Это позволяет объектам-мокам проходить проверки *isinstance* для объекта, который они заменяют или маскируют под:515516```python517>>> mock = Mock(spec=3)518>>> isinstance(mock, int)519True520```521522Атрибуту *\_\_class\_\_* можно присваивать значение, что позволяет моку проходить проверку *isinstance* без необходимости использовать spec:523524```python525>>> mock = Mock()526>>> mock.__class__ = dict527>>> isinstance(mock, dict)528True529```530531#### `class unittest.mock.NonCallableMock(spec=None, wraps=None, name=None, spec_set=None, **kwargs)`532533Невызываемая версия *Mock*. Параметры конструктора имеют тот же смысл, что и у *Mock*, за исключением *return\_value* и *side\_effect*, которые не имеют смысла для невызываемого мока.534535Объекты-моки, использующие класс или экземпляр в качестве *spec* или *spec\_set*, способны проходить проверки *isinstance*:536537```python538>>> mock = Mock(spec=SomeClass)539>>> isinstance(mock, SomeClass)540True541>>> mock = Mock(spec_set=SomeClass())542>>> isinstance(mock, SomeClass)543True544```545546Классы *Mock* поддерживают имитацию магических методов. Полные подробности см. в разделе [*магические методы*](https://python-all.ru/3.3/library/unittest.mock.html#magic-methods).547548Классы моков и декораторы [`patch()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.patch) принимают произвольные ключевые аргументы для настройки. Для декораторов *patch* ключевые слова передаются конструктору создаваемого мока. Ключевые аргументы предназначены для настройки атрибутов мока:549550```python551>>> m = MagicMock(attribute=3, other='fish')552>>> m.attribute5533554>>> m.other555'fish'556```557558Возвращаемое значение и побочный эффект дочерних mock-объектов можно установить таким же образом, используя точечную нотацию. Поскольку точечные имена нельзя использовать непосредственно в вызове, необходимо создать словарь и распаковать его с помощью *\*\**:559560```python561>>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}562>>> mock = Mock(some_attribute='eggs', **attrs)563>>> mock.some_attribute564'eggs'565>>> mock.method()5663567>>> mock.other()568Traceback (most recent call last):569  ...570KeyError571```572573#### `class unittest.mock.PropertyMock(*args, **kwargs)`574575Макет, предназначенный для использования в качестве свойства или другого дескриптора в классе. *PropertyMock* предоставляет методы *\_\_get\_\_* и *\_\_set\_\_*, чтобы можно было указать возвращаемое значение при его получении.576577Получение экземпляра *PropertyMock* из объекта вызывает макет без аргументов. Установка значения вызывает макет с устанавливаемым значением.578579```python580>>> class Foo:581...     @property582...     def foo(self):583...         return 'something'584...     @foo.setter585...     def foo(self, value):586...         pass587...588>>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo:589...     mock_foo.return_value = 'mockity-mock'590...     this_foo = Foo()591...     print this_foo.foo592...     this_foo.foo = 6593...594mockity-mock595>>> mock_foo.mock_calls596[call(), call(6)]597```598599Из-за особенностей хранения атрибутов макета невозможно напрямую присоединить *PropertyMock* к объекту макета. Вместо этого его можно присоединить к объекту типа макета:600601```python602>>> m = MagicMock()603>>> p = PropertyMock(return_value=3)604>>> type(m).foo = p605>>> m.foo6063607>>> p.assert_called_once_with()608```609610### 26.4.2.1. Вызов611612Объекты-макеты вызываемы. Вызов возвращает значение, установленное в атрибуте [`return_value`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.return_value). По умолчанию возвращаемое значение – новый объект Mock; он создаётся при первом обращении к возвращаемому значению (явном или через вызов макета), но затем сохраняется и возвращается при каждом последующем вызове.613614Вызовы объекта будут записаны в таких атрибутах, как [`call_args`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args) и [`call_args_list`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args_list).615616Если задан [`side_effect`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.side_effect), он будет вызван после того, как вызов будет записан, так что если *side\_effect* вызывает исключение, вызов всё равно записывается.617618Простейший способ заставить макет возбуждать исключение при вызове – сделать [`side_effect`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.side_effect) классом или экземпляром исключения:619620```python621>>> m = MagicMock(side_effect=IndexError)622>>> m(1, 2, 3)623Traceback (most recent call last):624  ...625IndexError626>>> m.mock_calls627[call(1, 2, 3)]628>>> m.side_effect = KeyError('Bang!')629>>> m('two', 'three', 'four')630Traceback (most recent call last):631  ...632KeyError: 'Bang!'633>>> m.mock_calls634[call(1, 2, 3), call('two', 'three', 'four')]635```636637Если *side\_effect* – это функция, то вызовы макета возвращают то, что возвращает эта функция. Функция *side\_effect* вызывается с теми же аргументами, что и макет. Это позволяет динамически изменять возвращаемое значение вызова в зависимости от входных данных:638639```python640>>> def side_effect(value):641...     return value + 1642...643>>> m = MagicMock(side_effect=side_effect)644>>> m(1)6452646>>> m(2)6473648>>> m.mock_calls649[call(1), call(2)]650```651652Если требуется, чтобы макет по-прежнему возвращал значение по умолчанию (новый макет) или любое заданное возвращаемое значение, есть два способа: либо вернуть *mock.return\_value* изнутри *side\_effect*, либо вернуть [`DEFAULT`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.DEFAULT):653654```python655>>> m = MagicMock()656>>> def side_effect(*args, **kwargs):657...     return m.return_value658...659>>> m.side_effect = side_effect660>>> m.return_value = 3661>>> m()6623663>>> def side_effect(*args, **kwargs):664...     return DEFAULT665...666>>> m.side_effect = side_effect667>>> m()6683669```670671Чтобы удалить *side\_effect* и вернуться к поведению по умолчанию, установите *side\_effect* в *None*:672673```python674>>> m = MagicMock(return_value=6)675>>> def side_effect(*args, **kwargs):676...     return 3677...678>>> m.side_effect = side_effect679>>> m()6803681>>> m.side_effect = None682>>> m()6836684```685686*side\_effect* также может быть любым итерируемым объектом. Повторные вызовы макета будут возвращать значения из итератора (пока он не исчерпается и не будет возбуждено *StopIteration*):687688```python689>>> m = MagicMock(side_effect=[1, 2, 3])690>>> m()6911692>>> m()6932694>>> m()6953696>>> m()697Traceback (most recent call last):698  ...699StopIteration700```701702Если какие-либо элементы итератора являются исключениями, они будут вызваны вместо того, чтобы быть возвращёнными:703704```python705>>> iterable = (33, ValueError, 66)706>>> m = MagicMock(side_effect=iterable)707>>> m()70833709>>> m()710Traceback (most recent call last):711 ...712ValueError713>>> m()71466715```716717### 26.4.2.2. Удаление атрибутов718719Объекты Mock создают атрибуты по запросу. Это позволяет им притворяться объектами любого типа.720721Может потребоваться, чтобы объект макета возвращал *False* на вызов *hasattr* или возбуждал *AttributeError* при получении атрибута. Это можно сделать, предоставив объект в качестве *spec* для макета, но это не всегда удобно.722723Атрибуты «блокируются» их удалением. После удаления при обращении к атрибуту будет возбуждено *AttributeError*.724725```python726>>> mock = MagicMock()727>>> hasattr(mock, 'm')728True729>>> del mock.m730>>> hasattr(mock, 'm')731False732>>> del mock.f733>>> mock.f734Traceback (most recent call last):735    ...736AttributeError: f737```738739### 26.4.2.3. Имена mock'ов и атрибут name740741Поскольку «name» – это аргумент конструктора [`Mock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock), если требуется, чтобы mock-объект имел атрибут «name», его нельзя просто передать при создании. Есть две альтернативы. Один из вариантов – использовать [`configure_mock()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.configure_mock):742743```python744>>> mock = MagicMock()745>>> mock.configure_mock(name='my_name')746>>> mock.name747'my_name'748```749750Более простой вариант – просто установить атрибут «name» после создания макета:751752```python753>>> mock = MagicMock()754>>> mock.name = "foo"755```756757### 26.4.2.4. Прикрепление моков в качестве атрибутов758759Когда mock прикрепляется как атрибут другого mock (или как возвращаемое значение), он становится «дочерним» по отношению к этому mock. Вызовы к дочернему объекту записываются в атрибуты [`method_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.method_calls) и [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls) родительского объекта. Это полезно для настройки дочерних mock'ов и последующего их прикрепления к родительскому, или для прикрепления mock'ов к родительскому, который записывает все вызовы к дочерним и позволяет делать утверждения о порядке вызовов между mock'ами:760761```python762>>> parent = MagicMock()763>>> child1 = MagicMock(return_value=None)764>>> child2 = MagicMock(return_value=None)765>>> parent.child1 = child1766>>> parent.child2 = child2767>>> child1(1)768>>> child2(2)769>>> parent.mock_calls770[call.child1(1), call.child2(2)]771```772773Исключение составляет случай, когда у макета есть имя. Это позволяет предотвратить «родительскую связь», если по какой-то причине вы не хотите, чтобы это происходило.774775```python776>>> mock = MagicMock()777>>> not_a_child = MagicMock(name='not-a-child')778>>> mock.attribute = not_a_child779>>> mock.attribute()780<MagicMock name='not-a-child()' id='...'>781>>> mock.mock_calls782[]783```784785Mock'ы, создаваемые [`patch()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.patch), автоматически получают имена. Чтобы прикрепить именованные mock'и к родительскому, используется метод [`attach_mock()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.attach_mock):786787```python788>>> thing1 = object()789>>> thing2 = object()790>>> parent = MagicMock()791>>> with patch('__main__.thing1', return_value=None) as child1:792...     with patch('__main__.thing2', return_value=None) as child2:793...         parent.attach_mock(child1, 'child1')794...         parent.attach_mock(child2, 'child2')795...         child1('one')796...         child2('two')797...798>>> parent.mock_calls799[call.child1('one'), call.child2('two')]800```801802| [\[1\]](https://python-all.ru/3.3/library/unittest.mock.html#id1) | Исключение составляют только магические методы и атрибуты (те, что имеют двойное подчёркивание в начале и конце). Макет не создаёт их, а вместо этого возбуждает `AttributeError`. Это связано с тем, что интерпретатор часто неявно запрашивает эти методы и *сильно* путается, получая новый объект Mock, когда ожидает магический метод. Если требуется поддержка магических методов, см. [*магические методы*](https://python-all.ru/3.3/library/unittest.mock.html#magic-methods). |803| --- | --- |804805## 26.4.3. Патчеры806807Декораторы patch используются для патчинга объектов только в пределах области видимости функции, которую они декорируют. Они автоматически обрабатывают отмену патчинга, даже если возникают исключения. Все эти функции также могут использоваться в операторах with или в качестве декораторов классов.808809### 26.4.3.1. patch810811> **Примечание**812>813> *patch* прост в использовании. Ключевой момент – выполнять подмену в правильном пространстве имён. См. раздел [где подменять](https://python-all.ru/3.3/library/unittest.mock.html#id4).814815#### `unittest.mock.patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)`816817*patch* работает как декоратор функции, декоратор класса или менеджер контекста. Внутри тела функции или блока with целевой объект *target* подменяется объектом *new*. При выходе из функции/блока with подмена отменяется.818819Если *new* опущен, целевой объект заменяется на [`MagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.MagicMock). Если *patch* используется как декоратор и *new* опущен, созданный макет передаётся как дополнительный аргумент декорированной функции. Если *patch* используется как менеджер контекста, созданный макет возвращается менеджером контекста.820821*target* должен быть строкой вида *'package.module.ClassName'*. *target* импортируется, и указанный объект заменяется объектом *new*, поэтому *target* должен быть импортируем из среды, из которой вызывается *patch*. Целевой объект импортируется при выполнении декорированной функции, а не во время декорирования.822823Именованные аргументы *spec* и *spec\_set* передаются в *MagicMock*, если patch создаёт его для вас.824825Кроме того, можно передать *spec=True* или *spec\_set=True*, что заставит patch передать в качестве объекта spec/spec\_set сам подменяемый объект.826827*new\_callable* позволяет указать другой класс или вызываемый объект, который будет вызван для создания объекта *new*. По умолчанию используется *MagicMock*.828829Более мощная форма *spec* – это *autospec*. Если задать *autospec=True*, макет будет создан со спецификацией, взятой у заменяемого объекта. Все атрибуты макета также будут иметь спецификацию соответствующего атрибута заменяемого объекта. У методов и функций, которые подменяются, будут проверяться аргументы, и при вызове с неправильной сигнатурой будет возбуждено *TypeError*. Для макетов, заменяющих класс, их возвращаемое значение («экземпляр») будет иметь ту же спецификацию, что и класс. См. функцию [`create_autospec()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.create_autospec) и [*Автоспецификация*](https://python-all.ru/3.3/library/unittest.mock.html#auto-speccing).830831Вместо *autospec=True* можно передать *autospec=some\_object*, чтобы использовать произвольный объект в качестве спецификации вместо заменяемого.832833По умолчанию *patch* не сможет заменить несуществующие атрибуты. Если передать *create=True*, и атрибут не существует, patch создаст его при вызове подменённой функции и удалит после. Это полезно для написания тестов на атрибуты, которые создаёт рабочий код во время выполнения. По умолчанию эта возможность отключена, так как может быть опасной. С её включением можно писать успешные тесты для API, которых на самом деле не существует!834835Patch можно использовать как декоратор класса *TestCase*. Он работает, декорируя каждый тестовый метод в классе. Это уменьшает шаблонный код, когда тестовые методы используют общий набор подмен. *patch* находит тесты, ища имена методов, начинающиеся с *patch.TEST\_PREFIX*. По умолчанию это *test*, что соответствует тому, как *unittest* находит тесты. Можно указать альтернативный префикс, задав *patch.TEST\_PREFIX*.836837Patch можно использовать как менеджер контекста с оператором with. В этом случае подмена применяется к вложенному блоку после with. Если использовать «as», подменённый объект будет связан с именем после «as»; это очень удобно, если *patch* создаёт объект макета.838839*patch* принимает произвольные именованные аргументы. Они будут переданы в *Mock* (или *new\_callable*) при создании.840841*patch.dict(...)*, *patch.multiple(...)* и *patch.object(...)* доступны для других сценариев использования.842843*patch* как декоратор функции, создающий макет и передающий его в декорированную функцию:844845```python846>>> @patch('__main__.SomeClass')847... def function(normal_argument, mock_class):848...     print(mock_class is SomeClass)849...850>>> function(None)851True852```853854Подмена класса заменяет класс экземпляром *MagicMock* *instance*. Если класс инстанцируется в тестируемом коде, то будет использоваться [`return_value`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.return_value) макета.855856Если класс инстанциируется несколько раз, можно использовать [`side_effect`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.side_effect), чтобы каждый раз возвращать новый mock. В качестве альтернативы можно установить *return\_value* в любое значение.857858Чтобы настроить возвращаемые значения методов экземпляров *instances* подменённого класса, необходимо сделать это на *return\_value*. Например:859860```python861>>> class Class:862...     def method(self):863...         pass864...865>>> with patch('__main__.Class') as MockClass:866...     instance = MockClass.return_value867...     instance.method.return_value = 'foo'868...     assert Class() is instance869...     assert Class().method() == 'foo'870...871```872873Если используется *spec* или *spec\_set*, и *patch* заменяет *класс*, то возвращаемое значение созданного макета будет иметь ту же спецификацию.874875```python876>>> Original = Class877>>> patcher = patch('__main__.Class', spec=True)878>>> MockClass = patcher.start()879>>> instance = MockClass()880>>> assert isinstance(instance, Original)881>>> patcher.stop()882```883884Аргумент *new\_callable* полезен, когда требуется использовать альтернативный класс вместо [`MagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.MagicMock) для создаваемого mock. Например, если нужно, чтобы использовался [`NonCallableMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.NonCallableMock):885886```python887>>> thing = object()888>>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing:889...     assert thing is mock_thing890...     thing()891...892Traceback (most recent call last):893  ...894TypeError: 'NonCallableMock' object is not callable895```896897Ещё один вариант использования – замена объекта экземпляром *io.StringIO*:898899```python900>>> from io import StringIO901>>> def foo():902...     print 'Something'903...904>>> @patch('sys.stdout', new_callable=StringIO)905... def test(mock_stdout):906...     foo()907...     assert mock_stdout.getvalue() == 'Something\n'908...909>>> test()910```911912Когда *patch* создаёт mock за вас, обычно первым делом нужно настроить этот mock. Часть этой настройки можно выполнить в самом вызове patch. Любые произвольные ключевые слова, переданные в вызов, будут использованы для установки атрибутов созданного mock:913914```python915>>> patcher = patch('__main__.thing', first='one', second='two')916>>> mock_thing = patcher.start()917>>> mock_thing.first918'one'919>>> mock_thing.second920'two'921```922923Кроме атрибутов создаваемого mock, можно также настроить атрибуты дочерних mock, такие как [`return_value`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.return_value) и [`side_effect`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.side_effect). Их нельзя передать напрямую как ключевые аргументы, но словарь с такими ключами можно развернуть в вызов *patch* с помощью *\*\**:924925```python926>>> config = {'method.return_value': 3, 'other.side_effect': KeyError}927>>> patcher = patch('__main__.thing', **config)928>>> mock_thing = patcher.start()929>>> mock_thing.method()9303931>>> mock_thing.other()932Traceback (most recent call last):933  ...934KeyError935```936937### 26.4.3.2. patch.object938939#### `patch.object(target, attribute, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)`940941Заменяет именованный член (*атрибут*) объекта (*цель*) на мок-объект.942943*patch.object* может использоваться как декоратор, декоратор класса или контекстный менеджер. Аргументы *new*, *spec*, *create*, *spec\_set*, *autospec* и *new\_callable* имеют тот же смысл, что и для *patch*. Как и *patch*, *patch.object* принимает произвольные ключевые аргументы для настройки создаваемого им mock-объекта.944945При использовании в качестве декоратора класса *patch.object* учитывает *patch.TEST\_PREFIX* для выбора методов, которые следует обернуть.946947*patch.object* можно вызывать с тремя или двумя аргументами. Форма с тремя аргументами принимает объект, который нужно заменить, имя атрибута и объект, на который нужно заменить атрибут.948949При вызове с двумя аргументами заменяющий объект опускается, и мок создаётся и передаётся как дополнительный аргумент в декорируемую функцию:950951```python952>>> @patch.object(SomeClass, 'class_method')953... def test(mock_method):954...     SomeClass.class_method(3)955...     mock_method.assert_called_with(3)956...957>>> test()958```959960*spec*, *create* и остальные аргументы *patch.object* имеют тот же смысл, что и для *patch*.961962### 26.4.3.3. patch.dict963964#### `patch.dict(in_dict, values=(), clear=False, **kwargs)`965966Исправляет словарь или подобный словарю объект и восстанавливает его исходное состояние после завершения теста.967968*in\_dict* может быть словарём или контейнером, подобным отображению. Если это отображение, оно должно как минимум поддерживать получение, установку и удаление элементов, а также итерацию по ключам.969970*in\_dict* также может быть строкой, задающей имя словаря, который затем будет получен через импорт.971972*values* может быть словарём значений, которые нужно установить в словаре. *values* также может быть итерируемым объектом, состоящим из пар *(key, value)*.973974Если *clear* равен true, то словарь будет очищен перед установкой новых значений.975976*patch.dict* также можно вызывать с произвольными ключевыми аргументами для установки значений в словаре.977978*patch.dict* может использоваться как контекстный менеджер, декоратор или декоратор класса. При использовании в качестве декоратора класса *patch.dict* учитывает *patch.TEST\_PREFIX* для выбора методов, которые следует обернуть.979980*patch.dict* можно использовать для добавления элементов в словарь или просто чтобы позволить тесту изменить словарь и гарантировать его восстановление после завершения теста.981982```python983>>> foo = {}984>>> with patch.dict(foo, {'newkey': 'newvalue'}):985...     assert foo == {'newkey': 'newvalue'}986...987>>> assert foo == {}988```989990```python991>>> import os992>>> with patch.dict('os.environ', {'newkey': 'newvalue'}):993...     print os.environ['newkey']994...995newvalue996>>> assert 'newkey' not in os.environ997```998999Ключевые слова можно использовать в вызове *patch.dict* для установки значений в словаре:10001001```python1002>>> mymodule = MagicMock()1003>>> mymodule.function.return_value = 'fish'1004>>> with patch.dict('sys.modules', mymodule=mymodule):1005...     import mymodule1006...     mymodule.function('some', 'args')1007...1008'fish'1009```10101011*patch.dict* можно использовать с объектами, похожими на словарь, но не являющимися словарями. Как минимум они должны поддерживать получение, установку и удаление элементов, а также итерацию или проверку вхождения. Это соответствует магическим методам *\_\_getitem\_\_*, *\_\_setitem\_\_*, *\_\_delitem\_\_* и *\_\_iter\_\_* или *\_\_contains\_\_*.10121013```python1014>>> class Container:1015...     def __init__(self):1016...         self.values = {}1017...     def __getitem__(self, name):1018...         return self.values[name]1019...     def __setitem__(self, name, value):1020...         self.values[name] = value1021...     def __delitem__(self, name):1022...         del self.values[name]1023...     def __iter__(self):1024...         return iter(self.values)1025...1026>>> thing = Container()1027>>> thing['one'] = 11028>>> with patch.dict(thing, one=2, two=3):1029...     assert thing['one'] == 21030...     assert thing['two'] == 31031...1032>>> assert thing['one'] == 11033>>> assert list(thing) == ['one']1034```10351036### 26.4.3.4. patch.multiple10371038#### `patch.multiple(target, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)`10391040Выполняет несколько патчей за один вызов. Принимает объект для патча (либо сам объект, либо строку для его импорта) и именованные аргументы для патчей:10411042```python1043with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'):1044    ...1045```10461047Используйте [`DEFAULT`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.DEFAULT) в качестве значения, если нужно, чтобы *patch.multiple* создал заглушки за вас. В этом случае созданные заглушки передаются в декорированную функцию по ключевому слову, а словарь возвращается, когда *patch.multiple* используется как контекстный менеджер.10481049*patch.multiple* может использоваться как декоратор, декоратор класса или контекстный менеджер. Аргументы *spec*, *spec\_set*, *create*, *autospec* и *new\_callable* имеют тот же смысл, что и для *patch*. Эти аргументы будут применены ко *всем* подменам, выполняемым с помощью *patch.multiple*.10501051При использовании в качестве декоратора класса *patch.multiple* учитывает *patch.TEST\_PREFIX* для выбора методов, которые следует обернуть.10521053Если вы хотите, чтобы *patch.multiple* создал заглушки за вас, вы можете использовать [`DEFAULT`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.DEFAULT) в качестве значения. Если вы используете *patch.multiple* как декоратор, созданные заглушки передаются в декорированную функцию по ключевому слову.10541055```python1056>>> thing = object()1057>>> other = object()1058```10591060```python1061>>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)1062... def test_function(thing, other):1063...     assert isinstance(thing, MagicMock)1064...     assert isinstance(other, MagicMock)1065...1066>>> test_function()1067```10681069*patch.multiple* может быть вложен с другими декораторами *patch*, но аргументы, переданные по ключевому слову, ставьте *после* любых стандартных аргументов, создаваемых *patch*:10701071```python1072>>> @patch('sys.exit')1073... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)1074... def test_function(mock_exit, other, thing):1075...     assert 'other' in repr(other)1076...     assert 'thing' in repr(thing)1077...     assert 'exit' in repr(mock_exit)1078...1079>>> test_function()1080```10811082Если *patch.multiple* используется как контекстный менеджер, возвращаемое значение – это словарь, в котором ключами служат имена созданных заглушек:10831084```python1085>>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values:1086...     assert 'other' in repr(values['other'])1087...     assert 'thing' in repr(values['thing'])1088...     assert values['thing'] is thing1089...     assert values['other'] is other1090...1091```10921093### 26.4.3.5. Методы patch: start и stop10941095Все объекты-подмены имеют методы *start* и *stop*. Они упрощают выполнение подмен в методах *setUp* или в ситуациях, когда требуется выполнить несколько подмен без вложенных декораторов или операторов with.10961097Чтобы их использовать, вызовите *patch*, *patch.object* или *patch.dict* как обычно и сохраните ссылку на возвращаемый объект *patcher*. Затем можно вызвать *start* для применения подмены и *stop* для её отмены.10981099Если вы используете *patch* для создания mock за вас, то этот mock будет возвращён вызовом *patcher.start*.11001101```python1102>>> patcher = patch('package.module.ClassName')1103>>> from package import module1104>>> original = module.ClassName1105>>> new_mock = patcher.start()1106>>> assert module.ClassName is not original1107>>> assert module.ClassName is new_mock1108>>> patcher.stop()1109>>> assert module.ClassName is original1110>>> assert module.ClassName is not new_mock1111```11121113Типичный пример использования – выполнение нескольких подмен в методе *setUp* класса *TestCase*:11141115```python1116>>> class MyTest(TestCase):1117...     def setUp(self):1118...         self.patcher1 = patch('package.module.Class1')1119...         self.patcher2 = patch('package.module.Class2')1120...         self.MockClass1 = self.patcher1.start()1121...         self.MockClass2 = self.patcher2.start()1122...1123...     def tearDown(self):1124...         self.patcher1.stop()1125...         self.patcher2.stop()1126...1127...     def test_something(self):1128...         assert package.module.Class1 is self.MockClass11129...         assert package.module.Class2 is self.MockClass21130...1131>>> MyTest('test_something').run()1132```11331134> **Внимание**1135>1136> Если вы используете этот приём, необходимо гарантировать, что подмена будет «отменена» вызовом *stop*. Это может быть сложнее, чем кажется, потому что если в `setUp` возникнет исключение, `tearDown` не будет вызван. [`unittest.TestCase.addCleanup()`](https://python-all.ru/3.3/library/unittest.html#unittest.TestCase.addCleanup) упрощает это:1137>1138> ```python1139> >>> class MyTest(TestCase):1140> ...     def setUp(self):1141> ...         patcher = patch('package.module.Class')1142> ...         self.MockClass = patcher.start()1143> ...         self.addCleanup(patcher.stop)1144> ...1145> ...     def test_something(self):1146> ...         assert package.module.Class is self.MockClass1147> ...1148> ```1149>1150> Вдобавок больше не нужно хранить ссылку на объект *patcher*.11511152Также можно остановить все запущенные подмены с помощью *patch.stopall*.11531154#### `patch.stopall()`11551156Останавливает все активные патчи. Останавливает только патчи, запущенные с помощью *start*.11571158### 26.4.3.6. TEST\_PREFIX11591160Все патчеры могут использоваться как декораторы классов. При таком использовании они оборачивают каждый тестовый метод класса. Патчеры распознают методы, начинающиеся с *test*, как тестовые. Это тот же способ, которым [`unittest.TestLoader`](https://python-all.ru/3.3/library/unittest.html#unittest.TestLoader) по умолчанию находит тестовые методы.11611162Возможно, вы захотите использовать другой префикс для своих тестов. Вы можете сообщить патчерам другой префикс, установив *patch.TEST\_PREFIX*:11631164```python1165>>> patch.TEST_PREFIX = 'foo'1166>>> value = 31167>>>1168>>> @patch('__main__.value', 'not three')1169... class Thing:1170...     def foo_one(self):1171...         print value1172...     def foo_two(self):1173...         print value1174...1175>>>1176>>> Thing().foo_one()1177not three1178>>> Thing().foo_two()1179not three1180>>> value118131182```11831184### 26.4.3.7. Вложение декораторов патчей11851186Если нужно выполнить несколько замен, можно просто наложить декораторы друг на друга.11871188Можно накладывать несколько декораторов патча, используя такой шаблон:11891190```python1191>>> @patch.object(SomeClass, 'class_method')1192... @patch.object(SomeClass, 'static_method')1193... def test(mock1, mock2):1194...     assert SomeClass.static_method is mock11195...     assert SomeClass.class_method is mock21196...     SomeClass.static_method('foo')1197...     SomeClass.class_method('bar')1198...     return mock1, mock21199...1200>>> mock1, mock2 = test()1201>>> mock1.assert_called_once_with('foo')1202>>> mock2.assert_called_once_with('bar')1203```12041205Обратите внимание: декораторы применяются снизу вверх. Это стандартный порядок применения декораторов в Python. Порядок созданных заглушек, передаваемых в тестовую функцию, соответствует этому порядку.12061207### 26.4.3.8. Где патчить12081209*patch* работает, (временно) заменяя объект, на который указывает *имя*, другим объектом. На один объект может указывать множество имён, поэтому для корректной работы патчинга необходимо убедиться, что патчится именно то имя, которое используется тестируемой системой.12101211Основной принцип: патч применяется там, где объект *ищется*, а это не обязательно то же место, где он определён. Несколько примеров помогут прояснить это.12121213Представим проект, который нужно протестировать, со следующей структурой:12141215```python1216a.py1217    -> Defines SomeClass12181219b.py1220    -> from a import SomeClass1221    -> some_function instantiates SomeClass1222```12231224Теперь мы хотим протестировать *some\_function*, но хотим замокать *SomeClass* с помощью *patch*. Проблема в том, что когда мы импортируем модуль b (а нам придётся это сделать), он импортирует *SomeClass* из модуля a. Если мы используем *patch* для мока *a.SomeClass*, это не повлияет на наш тест: модуль b уже содержит ссылку на *настоящий* *SomeClass*, и создаётся впечатление, что патчинг не сработал.12251226Ключ в том, чтобы патчить *SomeClass* там, где он используется (или где он ищется). В данном случае *some\_function* на самом деле будет искать *SomeClass* в модуле b, куда мы его импортировали. Патчинг должен выглядеть так:12271228```python1229@patch('b.SomeClass')1230```12311232Однако рассмотрим альтернативный сценарий, когда вместо *from a import SomeClass* модуль b использует *import a* и *some\_function* использует *a.SomeClass*. Обе формы импорта распространены. В этом случае класс, который мы хотим замокать, ищется в модуле a, поэтому мы должны патчить *a.SomeClass*:12331234```python1235@patch('a.SomeClass')1236```12371238### 26.4.3.9. Патчинг дескрипторов и прокси-объектов12391240И [patch](https://python-all.ru/3.3/library/unittest.mock.html#patch), и [patch.object](https://python-all.ru/3.3/library/unittest.mock.html#patch-object) корректно заменяют и восстанавливают дескрипторы: методы класса, статические методы и свойства. Заменять их следует на *классе*, а не на экземпляре. Они также работают с *некоторыми* объектами, проксирующими доступ к атрибутам, например, [объект настроек Django](https://python-all.ru/3.3/library/unittest.mock.html).12411242## 26.4.4. MagicMock и поддержка магических методов12431244### 26.4.4.1. Подмена магических методов12451246[`Mock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock) поддерживает подмену методов протоколов Python, также известных как «магические методы». Это позволяет мок-объектам заменять контейнеры или другие объекты, реализующие протоколы Python.12471248Поскольку магические методы ищутся иначе, чем обычные методы [\[2\]](https://python-all.ru/3.3/library/unittest.mock.html#id7), эта поддержка была реализована специально. Это означает, что поддерживаются только определённые магические методы. Список поддерживаемых методов включает *почти* все. Если каких-то не хватает, пожалуйста, сообщите.12491250Магические методы подменяются установкой нужного метода в функцию или экземпляр мока. Если используется функция, она *обязана* принимать `self` в качестве первого аргумента [\[3\]](https://python-all.ru/3.3/library/unittest.mock.html#id8).12511252```python1253>>> def __str__(self):1254...     return 'fooble'1255...1256>>> mock = Mock()1257>>> mock.__str__ = __str__1258>>> str(mock)1259'fooble'1260```12611262```python1263>>> mock = Mock()1264>>> mock.__str__ = Mock()1265>>> mock.__str__.return_value = 'fooble'1266>>> str(mock)1267'fooble'1268```12691270```python1271>>> mock = Mock()1272>>> mock.__iter__ = Mock(return_value=iter([]))1273>>> list(mock)1274[]1275```12761277Один из вариантов использования – мокинг объектов, используемых в качестве менеджеров контекста в операторе *with*:12781279```python1280>>> mock = Mock()1281>>> mock.__enter__ = Mock(return_value='foo')1282>>> mock.__exit__ = Mock(return_value=False)1283>>> with mock as m:1284...     assert m == 'foo'1285...1286>>> mock.__enter__.assert_called_with()1287>>> mock.__exit__.assert_called_with(None, None, None)1288```12891290Вызовы магических методов не отображаются в [`method_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.method_calls), но записываются в [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls).12911292> **Примечание**1293>1294> Если при создании мока используется именованный аргумент *spec*, то попытка установить магический метод, отсутствующий в спецификации, вызовет *AttributeError*.12951296Полный список поддерживаемых магических методов:12971298- `__hash__`, `__sizeof__`, `__repr__` и `__str__`1299- `__dir__`, `__format__` и `__subclasses__`1300- `__floor__`, `__trunc__` и `__ceil__`1301- Сравнения: `__cmp__`, `__lt__`, `__gt__`, `__le__`, `__ge__`, `__eq__` и `__ne__`1302- Методы контейнера: `__getitem__`, `__setitem__`, `__delitem__`, `__contains__`, `__len__`, `__iter__`, `__getslice__`, `__setslice__`, `__reversed__` и `__missing__`1303- Контекстный менеджер: `__enter__` и `__exit__`1304- Унарные числовые методы: `__neg__`, `__pos__` и `__invert__`1305- Числовые методы (включая правосторонние и варианты с изменением объекта): `__add__`, `__sub__`, `__mul__`, `__div__`, `__floordiv__`, `__mod__`, `__divmod__`, `__lshift__`, `__rshift__`, `__and__`, `__xor__`, `__or__` и `__pow__`1306- Методы числового преобразования: `__complex__`, `__int__`, `__float__`, `__index__` и `__coerce__`1307- Методы дескрипторов: `__get__`, `__set__` и `__delete__`1308- Сериализация (pickle): `__reduce__`, `__reduce_ex__`, `__getinitargs__`, `__getnewargs__`, `__getstate__` и `__setstate__`13091310Следующие методы существуют, но *не* поддерживаются, так как либо используются в mock, либо не могут быть установлены динамически, либо могут вызывать проблемы:13111312- `__getattr__`, `__setattr__`, `__init__` и `__new__`1313- `__prepare__`, `__instancecheck__`, `__subclasscheck__`, `__del__`13141315### 26.4.4.2. Magic Mock13161317Существует два варианта *MagicMock*: *MagicMock* и *NonCallableMagicMock*.13181319#### `class unittest.mock.MagicMock(*args, **kw)`13201321`MagicMock` – это подкласс [`Mock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock) с реализациями по умолчанию большинства магических методов. Можно использовать `MagicMock`, не настраивая магические методы вручную.13221323Параметры конструктора имеют тот же смысл, что и для [`Mock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock).13241325Если используются аргументы *spec* или *spec\_set*, то будут созданы *только* магические методы, которые существуют в спецификации.13261327#### `class unittest.mock.NonCallableMagicMock(*args, **kw)`13281329Невызываемая версия *MagicMock*.13301331Параметры конструктора имеют тот же смысл, что и для [`MagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.MagicMock), за исключением *return\_value* и *side\_effect*, которые не имеют смысла для невызываемого мока.13321333Магические методы настраиваются с помощью объектов *MagicMock*, поэтому их можно конфигурировать и использовать обычным образом:13341335```python1336>>> mock = MagicMock()1337>>> mock[3] = 'fish'1338>>> mock.__setitem__.assert_called_with(3, 'fish')1339>>> mock.__getitem__.return_value = 'result'1340>>> mock[2]1341'result'1342```13431344По умолчанию многие методы протокола должны возвращать объекты определенного типа. Эти методы предварительно настроены с возвращаемым значением по умолчанию, так что их можно использовать, ничего не делая, если возвращаемое значение не интересует. Вы всё еще можете *установить* возвращаемое значение вручную, если хотите изменить значение по умолчанию.13451346Методы и их значения по умолчанию:13471348- `__lt__`: NotImplemented1349- `__gt__`: NotImplemented1350- `__le__`: NotImplemented1351- `__ge__`: NotImplemented1352- `__int__`: 11353- `__contains__`: False1354- `__len__`: 11355- `__iter__`: iter(\[\])1356- `__exit__`: False1357- `__complex__`: 1j1358- `__float__`: 1.01359- `__bool__`: True1360- `__index__`: 11361- `__hash__`: хэш по умолчанию для мока1362- `__str__`: строковое представление по умолчанию для мока1363- `__sizeof__`: размер по умолчанию для мока13641365Например:13661367```python1368>>> mock = MagicMock()1369>>> int(mock)137011371>>> len(mock)137201373>>> list(mock)1374[]1375>>> object() in mock1376False1377```13781379Два метода сравнения на равенство, *\_\_eq\_\_* и *\_\_ne\_\_*, особые. По умолчанию они сравнивают объекты по идентичности, используя побочный эффект, если только не изменить их возвращаемое значение, чтобы оно возвращало что-то другое:13801381```python1382>>> MagicMock() == 31383False1384>>> MagicMock() != 31385True1386>>> mock = MagicMock()1387>>> mock.__eq__.return_value = True1388>>> mock == 31389True1390```13911392Возвращаемое значение *MagicMock.\_\_iter\_\_* может быть любым итерируемым объектом и не обязано быть итератором:13931394```python1395>>> mock = MagicMock()1396>>> mock.__iter__.return_value = ['a', 'b', 'c']1397>>> list(mock)1398['a', 'b', 'c']1399>>> list(mock)1400['a', 'b', 'c']1401```14021403Если возвращаемое значение *является* итератором, то однократная итерация по нему израсходует его, и последующие итерации приведут к пустому списку:14041405```python1406>>> mock.__iter__.return_value = iter(['a', 'b', 'c'])1407>>> list(mock)1408['a', 'b', 'c']1409>>> list(mock)1410[]1411```14121413У `MagicMock` настроены все поддерживаемые магические методы, за исключением некоторых устаревших и редко используемых. При желании их можно настроить.14141415Магические методы, которые поддерживаются, но не настроены по умолчанию в `MagicMock`:14161417- `__subclasses__`1418- `__dir__`1419- `__format__`1420- `__get__`, `__set__` и `__delete__`1421- `__reversed__` и `__missing__`1422- `__reduce__`, `__reduce_ex__`, `__getinitargs__`, `__getnewargs__`, `__getstate__` и `__setstate__`1423- `__getformat__` и `__setformat__`14241425| [\[2\]](https://python-all.ru/3.3/library/unittest.mock.html#id5) | Магические методы *должны* искаться в классе, а не в экземпляре. Разные версии Python непоследовательны в применении этого правила. Поддерживаемые методы протокола должны работать во всех поддерживаемых версиях Python. |1426| --- | --- |14271428| [\[3\]](https://python-all.ru/3.3/library/unittest.mock.html#id6) | Функция фактически прикрепляется к классу, но каждый экземпляр `Mock` остаётся изолированным от других. |1429| --- | --- |14301431## 26.4.5. Вспомогательные объекты14321433### 26.4.5.1. sentinel14341435#### `unittest.mock.sentinel`14361437Объект `sentinel` предоставляет удобный способ создания уникальных объектов для тестов.14381439Атрибуты создаются по запросу при обращении к ним по имени. Обращение к одному и тому же атрибуту всегда возвращает один и тот же объект. Возвращаемые объекты имеют понятное строковое представление (repr), чтобы сообщения об ошибках тестов были читаемыми.14401441Иногда при тестировании нужно проверить, что определённый объект передаётся в качестве аргумента другому методу или возвращается из него. Часто для этого создают именованные sentinel-объекты. *sentinel* предоставляет удобный способ создания и проверки идентичности таких объектов.14421443В этом примере мы подменяем (monkey-patch) *method*, чтобы он возвращал *sentinel.some\_object*:14441445```python1446>>> real = ProductionClass()1447>>> real.method = Mock(name="method")1448>>> real.method.return_value = sentinel.some_object1449>>> result = real.method()1450>>> assert result is sentinel.some_object1451>>> sentinel.some_object1452sentinel.some_object1453```14541455### 26.4.5.2. DEFAULT14561457#### `unittest.mock.DEFAULT`14581459Объект *DEFAULT* – это предварительно созданный sentinel (на самом деле *sentinel.DEFAULT*). Он может использоваться функциями [`side_effect`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.side_effect) для указания того, что следует использовать обычное возвращаемое значение.14601461### 26.4.5.3. call14621463#### `unittest.mock.call(*args, **kwargs)`14641465*call* – это вспомогательный объект для создания более простых утверждений, для сравнения с [`call_args`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args), [`call_args_list`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args_list), [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls) и [`method_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.method_calls). *call* также может использоваться с [`assert_has_calls()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.assert_has_calls).14661467```python1468>>> m = MagicMock(return_value=None)1469>>> m(1, 2, a='foo', b='bar')1470>>> m()1471>>> m.call_args_list == [call(1, 2, a='foo', b='bar'), call()]1472True1473```14741475#### `call.call_list()`14761477Для объекта call, представляющего несколько вызовов, *call\_list* возвращает список всех промежуточных вызовов, а также конечного вызова.14781479*call\_list* особенно полезен для создания утверждений по поводу «цепочечных вызовов». Цепочечный вызов – это несколько вызовов в одной строке кода. Это приводит к появлению нескольких записей в [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls) у мока. Ручное построение последовательности вызовов может быть утомительным.14801481[`call_list()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.call.call_list) может построить последовательность вызовов из того же цепочечного вызова:14821483```python1484>>> m = MagicMock()1485>>> m(1).method(arg='foo').other('bar')(2.0)1486<MagicMock name='mock().method().other()()' id='...'>1487>>> kall = call(1).method(arg='foo').other('bar')(2.0)1488>>> kall.call_list()1489[call(1),1490 call().method(arg='foo'),1491 call().method().other('bar'),1492 call().method().other()(2.0)]1493>>> m.mock_calls == kall.call_list()1494True1495```14961497Объект *call* представляет собой кортеж либо из (позиционные аргументы, именованные аргументы), либо (имя, позиционные аргументы, именованные аргументы) в зависимости от способа его создания. Когда вы создаёте их самостоятельно, это не особенно интересно, но объекты *call*, находящиеся в атрибутах [`Mock.call_args`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args), [`Mock.call_args_list`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args_list) и [`Mock.mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls), можно исследовать, чтобы извлечь содержащиеся в них отдельные аргументы.14981499Объекты *call* в [`Mock.call_args`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args) и [`Mock.call_args_list`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args_list) представляют собой двойки (позиционные аргументы, именованные аргументы), тогда как объекты *call* в [`Mock.mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls), а также те, которые вы создаёте сами, являются тройками (имя, позиционные аргументы, именованные аргументы).15001501Вы можете использовать их «кортежность», чтобы извлекать отдельные аргументы для более сложной интроспекции и проверок. Позиционные аргументы – это кортеж (пустой кортеж, если позиционных аргументов нет), а именованные аргументы – это словарь:15021503```python1504>>> m = MagicMock(return_value=None)1505>>> m(1, 2, 3, arg='one', arg2='two')1506>>> kall = m.call_args1507>>> args, kwargs = kall1508>>> args1509(1, 2, 3)1510>>> kwargs1511{'arg2': 'two', 'arg': 'one'}1512>>> args is kall[0]1513True1514>>> kwargs is kall[1]1515True1516```15171518```python1519>>> m = MagicMock()1520>>> m.foo(4, 5, 6, arg='two', arg2='three')1521<MagicMock name='mock.foo()' id='...'>1522>>> kall = m.mock_calls[0]1523>>> name, args, kwargs = kall1524>>> name1525'foo'1526>>> args1527(4, 5, 6)1528>>> kwargs1529{'arg2': 'three', 'arg': 'two'}1530>>> name is m.mock_calls[0][0]1531True1532```15331534### 26.4.5.4. create\_autospec15351536#### `unittest.mock.create_autospec(spec, spec_set=False, instance=False, **kwargs)`15371538Создаёт макет-объект, используя другой объект в качестве спецификации. Атрибуты макета будут использовать соответствующий атрибут объекта *spec* в качестве своей спецификации.15391540У макетируемых функций или методов будут проверяться аргументы, чтобы убедиться, что они вызываются с правильной сигнатурой.15411542Если *spec\_set* равно *True*, то попытка установить атрибуты, которых нет в объекте спецификации, вызовет *AttributeError*.15431544Если класс используется в качестве спецификации, то возвращаемое значение мока (экземпляр класса) будет иметь ту же спецификацию. Класс можно использовать в качестве спецификации для объекта-экземпляра, передав *instance=True*. Возвращаемый мок будет вызываемым, только если экземпляры мока являются вызываемыми.15451546*create\_autospec* также принимает произвольные именованные аргументы, которые передаются конструктору создаваемого мока.15471548Смотрите [*Autospeccing*](https://python-all.ru/3.3/library/unittest.mock.html#auto-speccing) с примерами использования автоспецификации с *create\_autospec* и аргументом *autospec* функции [`patch()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.patch).15491550### 26.4.5.5. ANY15511552#### `unittest.mock.ANY`15531554Иногда требуется проверять только *некоторые* из аргументов в вызове mock, либо не обращать внимания на часть аргументов, либо извлекать их по отдельности из [`call_args`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.call_args) и выполнять более сложные проверки.15551556Чтобы игнорировать определённые аргументы, можно передавать объекты, которые сравниваются равными *чему угодно*. Тогда вызовы [`assert_called_with()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.assert_called_with) и [`assert_called_once_with()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.assert_called_once_with) будут успешными независимо от того, что было передано.15571558```python1559>>> mock = Mock(return_value=None)1560>>> mock('foo', bar=object())1561>>> mock.assert_called_once_with('foo', bar=ANY)1562```15631564*ANY* также можно использовать при сравнении со списками вызовов, например [`mock_calls`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.mock_calls):15651566```python1567>>> m = MagicMock(return_value=None)1568>>> m(1)1569>>> m(1, 2)1570>>> m(object())1571>>> m.mock_calls == [call(1), call(1, 2), ANY]1572True1573```15741575### 26.4.5.6. FILTER\_DIR15761577#### `unittest.mock.FILTER_DIR`15781579*FILTER\_DIR* – это переменная уровня модуля, которая управляет тем, как mock-объекты реагируют на *dir* (только для Python 2.6 или новее). По умолчанию *True*, что приводит к использованию фильтрации, описанной ниже, для отображения только полезных членов. Если вам не нравится эта фильтрация или нужно отключить её для диагностики, установите *mock.FILTER\_DIR = False*.15801581При включённой фильтрации *dir(some\_mock)* показывает только полезные атрибуты и включает любые динамически созданные атрибуты, которые обычно не отображаются. Если mock был создан с *spec* (или, конечно, *autospec*), то отображаются все атрибуты оригинала, даже если к ним ещё не обращались:15821583```python1584>>> dir(Mock())1585['assert_any_call',1586 'assert_called_once_with',1587 'assert_called_with',1588 'assert_has_calls',1589 'attach_mock',1590 ...1591>>> from urllib import request1592>>> dir(Mock(spec=request))1593['AbstractBasicAuthHandler',1594 'AbstractDigestAuthHandler',1595 'AbstractHTTPHandler',1596 'BaseHandler',1597 ...1598```15991600Многие не очень полезные (приватные для *Mock*, а не для имитируемого объекта) атрибуты с префиксом из одного или двух подчёркиваний отфильтровываются из результата вызова *dir* на *Mock*. Если вам не нравится такое поведение, вы можете отключить его, установив переключатель уровня модуля *FILTER\_DIR*:16011602```python1603>>> from unittest import mock1604>>> mock.FILTER_DIR = False1605>>> dir(mock.Mock())1606['_NonCallableMock__get_return_value',1607 '_NonCallableMock__get_side_effect',1608 '_NonCallableMock__return_value_doc',1609 '_NonCallableMock__set_return_value',1610 '_NonCallableMock__set_side_effect',1611 '__call__',1612 '__class__',1613 ...1614```16151616В качестве альтернативы можно просто использовать *vars(my\_mock)* (члены экземпляра) и *dir(type(my\_mock))* (члены типа), чтобы обойти фильтрацию независимо от *mock.FILTER\_DIR*.16171618### 26.4.5.7. mock\_open16191620#### `unittest.mock.mock_open(mock=None, read_data=None)`16211622Вспомогательная функция для создания mock-объекта, заменяющего использование *open*. Она работает для *open*, вызываемого напрямую или используемого в качестве контекстного менеджера.16231624Аргумент *mock* – это настраиваемый mock-объект. Если *None* (по умолчанию), для вас будет создан *MagicMock* с API, ограниченным методами и атрибутами, доступными в стандартных файловых дескрипторах.16251626*read\_data* – это строка, которую должен возвращать метод *~io.IOBase.read* файлового дескриптора. По умолчанию это пустая строка.16271628Использование *open* в качестве контекстного менеджера – отличный способ гарантировать правильное закрытие файловых дескрипторов, и становится всё более распространённым:16291630```python1631with open('/some/path', 'w') as f:1632    f.write('something')1633```16341635Проблема в том, что даже если вы имитируете вызов *open*, именно *возвращаемый объект* используется в качестве контекстного менеджера (и у него вызываются *\_\_enter\_\_* и *\_\_exit\_\_*).16361637Создание моков для контекстных менеджеров с помощью [`MagicMock`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.MagicMock) – достаточно распространённая и сложная задача, поэтому вспомогательная функция оказывается полезной.16381639```python1640>>> m = mock_open()1641>>> with patch('__main__.open', m, create=True):1642...     with open('foo', 'w') as h:1643...         h.write('some stuff')1644...1645>>> m.mock_calls1646[call('foo', 'w'),1647 call().__enter__(),1648 call().write('some stuff'),1649 call().__exit__(None, None, None)]1650>>> m.assert_called_once_with('foo', 'w')1651>>> handle = m()1652>>> handle.write.assert_called_once_with('some stuff')1653```16541655А для чтения файлов:16561657```python1658>>> with patch('__main__.open', mock_open(read_data='bibble'), create=True) as m:1659...     with open('foo') as h:1660...         result = h.read()1661...1662>>> m.assert_called_once_with('foo')1663>>> assert result == 'bibble'1664```16651666### 26.4.5.8. Autospeccing16671668Автоспецификация основана на существующей функции *spec* в mock. Она ограничивает API mock-объектов API исходного объекта (спецификации), но является рекурсивной (реализована лениво), так что атрибуты mock-объектов имеют только тот же API, что и атрибуты спецификации. Кроме того, имитируемые функции/методы имеют ту же сигнатуру вызова, что и оригинал, поэтому они вызывают *TypeError* при неправильном вызове.16691670Прежде чем я объясню, как работает автоспекинг, вот почему он нужен.16711672*Mock* – это очень мощный и гибкий объект, но у него есть два недостатка при использовании для имитации объектов в тестируемой системе. Один из этих недостатков специфичен для API *Mock*, а другой – более общая проблема использования mock-объектов.16731674Сначала проблема, специфичная для *Mock*. *Mock* имеет два чрезвычайно удобных метода проверки: [`assert_called_with()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.assert_called_with) и [`assert_called_once_with()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.Mock.assert_called_once_with).16751676```python1677>>> mock = Mock(name='Thing', return_value=None)1678>>> mock(1, 2, 3)1679>>> mock.assert_called_once_with(1, 2, 3)1680>>> mock(1, 2, 3)1681>>> mock.assert_called_once_with(1, 2, 3)1682Traceback (most recent call last):1683 ...1684AssertionError: Expected 'mock' to be called once. Called 2 times.1685```16861687Поскольку mock-объекты автоматически создают атрибуты по требованию и позволяют вызывать их с произвольными аргументами, опечатка в имени одного из этих методов проверок приводит к тому, что проверка просто исчезает:16881689```pycon1690>>> mock = Mock(name='Thing', return_value=None)1691>>> mock(1, 2, 3)1692>>> mock.assret_called_once_with(4, 5, 6)1693```16941695Из-за опечатки тесты могут проходить молча и неправильно.16961697The second issue is more general to mocking. If you refactor some of your code, rename members and so on, any tests for code that is still using the *old api* but uses mocks instead of the real objects will still pass. This means your tests can all pass even though your code is broken.16981699Обратите внимание, что это ещё одна причина, по которой нужны интеграционные тесты, а не только модульные. Тестировать всё изолированно – это хорошо, но если вы не тестируете, как ваши модули «соединены вместе», всё ещё остаётся много места для ошибок, которые тесты могли бы выявить.17001701*mock* уже предоставляет функцию для решения этой проблемы, называемую speccing (спецификация). Если использовать класс или экземпляр в качестве *spec* для mock, то можно будет обращаться только к тем атрибутам mock, которые существуют в реальном классе:17021703```python1704>>> from urllib import request1705>>> mock = Mock(spec=request.Request)1706>>> mock.assret_called_with1707Traceback (most recent call last):1708 ...1709AttributeError: Mock object has no attribute 'assret_called_with'1710```17111712Spec применяется только к самому mock, поэтому у нас всё ещё есть та же проблема с любыми методами на mock:17131714```pycon1715>>> mock.has_data()1716<mock.Mock object at 0x...>1717>>> mock.has_data.assret_called_with()1718```17191720Автоспецификация решает эту проблему. Вы можете либо передать *autospec=True* в *patch* / *patch.object*, либо использовать функцию *create\_autospec* для создания mock с спецификацией. Если использовать аргумент *autospec=True* в *patch*, то заменяемый объект будет использоваться в качестве объекта спецификации. Поскольку спецификация выполняется «лениво» (спецификация создаётся по мере обращения к атрибутам mock), вы можете использовать её с очень сложными или глубоко вложенными объектами (например, модулями, которые импортируют модули, которые импортируют модули) без значительного снижения производительности.17211722Вот пример его использования:17231724```python1725>>> from urllib import request1726>>> patcher = patch('__main__.request', autospec=True)1727>>> mock_request = patcher.start()1728>>> request is mock_request1729True1730>>> mock_request.Request1731<MagicMock name='request.Request' spec='Request' id='...'>1732```17331734Видно, что *request.Request* имеет спецификацию. *request.Request* принимает два аргумента в конструкторе (один из которых – *self*). Вот что произойдёт, если попытаться вызвать его неправильно:17351736```python1737>>> req = request.Request()1738Traceback (most recent call last):1739 ...1740TypeError: <lambda>() takes at least 2 arguments (1 given)1741```17421743Spec также применяется к инстанцированным классам (т.е. возвращаемому значению specced-моков):17441745```python1746>>> req = request.Request('foo')1747>>> req1748<NonCallableMagicMock name='request.Request()' spec='Request' id='...'>1749```17501751Объекты *Request* не являются вызываемыми, поэтому возвращаемое значение при создании экземпляра нашего имитированного *request.Request* – это невызываемый mock. При наличии спецификации любые опечатки в наших проверках вызовут правильную ошибку:17521753```python1754>>> req.add_header('spam', 'eggs')1755<MagicMock name='request.Request().add_header()' id='...'>1756>>> req.add_header.assret_called_with1757Traceback (most recent call last):1758 ...1759AttributeError: Mock object has no attribute 'assret_called_with'1760>>> req.add_header.assert_called_with('spam', 'eggs')1761```17621763Во многих случаях вы сможете просто добавить *autospec=True* в существующие вызовы *patch* и тем самым защититься от ошибок, вызванных опечатками и изменениями API.17641765Помимо использования *autospec* через *patch*, существует [`create_autospec()`](https://python-all.ru/3.3/library/unittest.mock.html#unittest.mock.create_autospec) для непосредственного создания макетов с автоспецификацией:17661767```python1768>>> from urllib import request1769>>> mock_request = create_autospec(request)1770>>> mock_request.Request('foo', 'bar')1771<NonCallableMagicMock name='mock.Request()' spec='Request' id='...'>1772```17731774Однако у этого подхода есть оговорки и ограничения, поэтому он не используется по умолчанию. Чтобы узнать, какие атрибуты доступны у объекта спецификации, autospec должен интроспектировать (получать доступ к атрибутам) спецификацию. Когда вы обращаетесь к атрибутам мока, под капотом происходит аналогичный обход оригинального объекта. Если у каких-то из ваших специфицированных объектов есть свойства или дескрипторы, которые могут запускать выполнение кода, то использовать autospec может не получиться. С другой стороны, гораздо лучше проектировать объекты так, чтобы интроспекция была безопасной [\[4\]](https://python-all.ru/3.3/library/unittest.mock.html#id10).17751776Более серьёзная проблема заключается в том, что атрибуты экземпляра часто создаются в методе *\_\_init\_\_* и вообще не существуют в классе. *autospec* не может знать о динамически создаваемых атрибутах и ограничивает API видимыми атрибутами.17771778```python1779>>> class Something:1780...   def __init__(self):1781...     self.a = 331782...1783>>> with patch('__main__.Something', autospec=True):1784...   thing = Something()1785...   thing.a1786...1787Traceback (most recent call last):1788  ...1789AttributeError: Mock object has no attribute 'a'1790```17911792Существует несколько способов решить эту проблему. Самый простой (хотя и не обязательно наименее раздражающий) – просто установить нужные атрибуты на моке после его создания. То, что *autospec* не позволяет получать атрибуты, которых нет в спецификации, не мешает вам их устанавливать:17931794```python1795>>> with patch('__main__.Something', autospec=True):1796...   thing = Something()1797...   thing.a = 331798...1799```18001801Существует более строгая версия как *spec*, так и *autospec*, которая *не позволяет* устанавливать несуществующие атрибуты. Это полезно, если вы хотите гарантировать, что ваш код *устанавливает* только допустимые атрибуты, но, очевидно, это блокирует данный конкретный сценарий:18021803```python1804>>> with patch('__main__.Something', autospec=True, spec_set=True):1805...   thing = Something()1806...   thing.a = 331807...1808Traceback (most recent call last):1809 ...1810AttributeError: Mock object has no attribute 'a'1811```18121813Вероятно, лучший способ решения проблемы – добавить атрибуты класса в качестве значений по умолчанию для членов экземпляра, инициализируемых в *\_\_init\_\_*. Обратите внимание, что если вы устанавливаете только атрибуты по умолчанию в *\_\_init\_\_*, то предоставление их через атрибуты класса (которые, конечно, разделяются между экземплярами) также быстрее. Например:18141815```python1816class Something:1817    a = 331818```18191820This brings up another issue. It is relatively common to provide a default value of *None* for members that will later be an object of a different type. *None* would be useless as a spec because it wouldn’t let you access *any* attributes or methods on it. As *None* is *never* going to be useful as a spec, and probably indicates a member that will normally of some other type, *autospec* doesn’t use a spec for members that are set to *None*. These will just be ordinary mocks (well - *MagicMocks*):18211822```python1823>>> class Something:1824...     member = None1825...1826>>> mock = create_autospec(Something)1827>>> mock.member.foo.bar.baz()1828<MagicMock name='mock.member.foo.bar.baz()' id='...'>1829```18301831Если изменение рабочих классов для добавления значений по умолчанию вам не подходит, есть и другие варианты. Один из них – просто использовать экземпляр в качестве спецификации вместо класса. Другой – создать подкласс рабочего класса и добавить значения по умолчанию в подкласс, не затрагивая рабочий класс. В обоих случаях требуется использовать альтернативный объект в качестве спецификации. К счастью, *patch* поддерживает это – можно просто передать альтернативный объект в качестве аргумента *autospec*:18321833```python1834>>> class Something:1835...   def __init__(self):1836...     self.a = 331837...1838>>> class SomethingForTest(Something):1839...   a = 331840...1841>>> p = patch('__main__.Something', autospec=SomethingForTest)1842>>> mock = p.start()1843>>> mock.a1844<NonCallableMagicMock name='Something.a' spec='int' id='...'>1845```18461847| [\[4\]](https://python-all.ru/3.3/library/unittest.mock.html#id9) | Это применимо только к классам или уже созданным экземплярам. Вызов имитированного класса для создания mock-экземпляра *не* создаёт реальный экземпляр. Выполняются только поиск атрибутов и вызовы *dir*. |1848| --- | --- |1849