# `unittest.mock` — mock object library

Added in version 3.3.

Вихідний код: Lib/unittest/mock.py

`unittest.mock` — це бібліотека для тестування на Python. Це дозволяє вам замінити частини вашої тестованої системи на фіктивні об’єкти та зробити твердження про те, як вони використовувалися.

`unittest.mock` надає базовий клас `Mock`, який усуває необхідність створювати безліч заглушок у вашому наборі тестів. Після виконання дії ви можете зробити твердження про те, які методи/атрибути були використані та аргументи, з якими вони були викликані. Ви також можете вказати значення, що повертаються, і встановити необхідні атрибути звичайним способом.

Крім того, mock надає декоратор `patch()`, який обробляє модуль виправлення та атрибути рівня класу в межах тесту, а також `sentinel` для створення унікальних об’єктів. Перегляньте короткий посібник (quick guide) для деяких прикладів використання `Mock`, `MagicMock` і `patch()`.

Mock розроблений для використання з `unittest` і базується на шаблоні «action -> assertion» замість «record -> replay», який використовується багатьма фреймворками мокінгу.

There is a backport of `unittest.mock` for earlier versions of Python, available as mock on PyPI.

## Короткий посібник

Об’єкти `Mock` і `MagicMock` створюють усі атрибути та методи під час доступу до них і зберігають відомості про те, як вони використовувалися. Ви можете налаштувати їх, щоб указати значення, що повертаються, або обмежити доступність атрибутів, а потім зробити твердження про те, як вони використовувалися:

    >>> from unittest.mock import MagicMock
    >>> thing = ProductionClass()
    >>> thing.method = MagicMock(return_value=3)
    >>> thing.method(3, 4, 5, key='value')
    3
    >>> thing.method.assert_called_with(3, 4, 5, key='value')

`side_effect` allows you to perform side effects, including raising an exception when a mock is called:

    >>> from unittest.mock import Mock
    >>> mock = Mock(side_effect=KeyError('foo'))
    >>> mock()
    Traceback (most recent call last):
     ...
    KeyError: 'foo'

    >>> values = {'a': 1, 'b': 2, 'c': 3}
    >>> def side_effect(arg):
    ...     return values[arg]
    ...
    >>> mock.side_effect = side_effect
    >>> mock('a'), mock('b'), mock('c')
    (1, 2, 3)
    >>> mock.side_effect = [5, 4, 3, 2, 1]
    >>> mock(), mock(), mock()
    (5, 4, 3)

Mock має багато інших способів налаштувати його та контролювати його поведінку. Наприклад, аргумент spec налаштовує макет на отримання специфікації з іншого об’єкта. Спроба отримати доступ до атрибутів або методів у макеті, які не існують у специфікації, закінчиться помилкою з `AttributeError`.

Декоратор/менеджер контексту `patch()` дозволяє легко імітувати класи чи об’єкти в тестованому модулі. Вказаний вами об’єкт буде замінено макетом (або іншим об’єктом) під час тесту та відновлено після завершення тесту:

    >>> from unittest.mock import patch
    >>> @patch('module.ClassName2')
    ... @patch('module.ClassName1')
    ... def test(MockClass1, MockClass2):
    ...     module.ClassName1()
    ...     module.ClassName2()
    ...     assert MockClass1 is module.ClassName1
    ...     assert MockClass2 is module.ClassName2
    ...     assert MockClass1.called
    ...     assert MockClass2.called
    ...
    >>> test()

Примітка

Коли ви вкладаєте декоратори латок, макети передаються до декорованої функції в тому ж порядку, в якому вони застосовані (звичайний Python порядок застосування декораторів). Це означає знизу вгору, тому у наведеному вище прикладі спочатку передається макет для `module.ClassName1`.

З `patch()` важливо, щоб ви латали об’єкти в просторі імен, де вони шукаються. Зазвичай це просто, але для короткого посібника прочитайте де патч.

Як і декоратор `patch()` можна використовувати як менеджер контексту в операторі with:

    >>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method:
    ...     thing = ProductionClass()
    ...     thing.method(1, 2, 3)
    ...
    >>> mock_method.assert_called_once_with(1, 2, 3)

Існує також `patch.dict()` для встановлення значень у словнику лише під час області видимості та відновлення словника до початкового стану після завершення тесту:

    >>> foo = {'key': 'value'}
    >>> original = foo.copy()
    >>> with patch.dict(foo, {'newkey': 'newvalue'}, clear=True):
    ...     assert foo == {'newkey': 'newvalue'}
    ...
    >>> assert foo == original

Mock підтримує знущання над Python магічні методи. Найпростіший спосіб використання магічних методів — це клас `MagicMock`. Це дозволяє вам робити такі речі, як:

    >>> mock = MagicMock()
    >>> mock.__str__.return_value = 'foobarbaz'
    >>> str(mock)
    'foobarbaz'
    >>> mock.__str__.assert_called_with()

Mock дозволяє вам призначати функції (або інші екземпляри Mock) магічним методам, і вони будуть викликані належним чином. Клас `MagicMock` — це просто варіант Mock, який містить усі магічні методи, попередньо створені для вас (ну, у всякому разі, всі корисні).

Нижче наведено приклад використання магічних методів із звичайним класом Mock:

    >>> mock = Mock()
    >>> mock.__str__ = Mock(return_value='wheeeeee')
    >>> str(mock)
    'wheeeeee'

Щоб переконатися, що макетні об’єкти у ваших тестах мають той самий API, що й об’єкти, які вони замінюють, ви можете використати auto-speccing. Автоматичну специфікацію можна виконати за допомогою аргументу autospec для виправлення або функції `create_autospec()`. Автоматична специфікація створює макетні об’єкти, які мають ті самі атрибути та методи, що й об’єкти, які вони замінюють, а будь-які функції та методи (включаючи конструктори) мають ту саму сигнатуру виклику, що й реальний об’єкт.

Це гарантує, що ваші макети не працюватимуть так само, як і ваш робочий код, якщо вони використовуються неправильно:

    >>> from unittest.mock import create_autospec
    >>> def function(a, b, c):
    ...     pass
    ...
    >>> mock_function = create_autospec(function, return_value='fishy')
    >>> mock_function(1, 2, 3)
    'fishy'
    >>> mock_function.assert_called_once_with(1, 2, 3)
    >>> mock_function('wrong arguments')
    Traceback (most recent call last):
     ...
    TypeError: missing a required argument: 'b'

`create_autospec()` також можна використовувати в класах, де він копіює сигнатуру методу `__init__`, і на викликаних об’єктах, де він копіює сигнатуру `__call__` методу.

## Імітаційний клас

`Mock` — це гнучкий макет об’єкта, призначений для заміни використання заглушок і тестових дублів у вашому коді. Макети можна викликати та створювати атрибути як нові макети під час доступу до них [1]. Доступ до того самого атрибута завжди повертатиме той самий макет. Mocks записують, як ви їх використовуєте, дозволяючи вам робити твердження про те, що з ними зробив ваш код.

`MagicMock` є підкласом `Mock` з усіма магічними методами, попередньо створеними та готовими до використання. Існують також варіанти без можливості виклику, корисні, коли ви знущаєтеся над об’єктами, які не можна викликати: `NonCallableMock` і `NonCallableMagicMock`

Декоратори `patch()` дозволяють легко тимчасово замінити класи в певному модулі на об’єкт `Mock`. За умовчанням `patch()` створить для вас `MagicMock`. Ви можете вказати альтернативний клас `Mock` за допомогою аргументу new_callable для `patch()`.

class unittest.mock.Mock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)

  Створіть новий об’єкт `Mock`. `Mock` приймає кілька додаткових аргументів, які визначають поведінку об’єкта Mock:

  - spec: це може бути або список рядків, або існуючий об’єкт (клас або екземпляр), який діє як специфікація для макетного об’єкта. Якщо ви передаєте об’єкт, тоді список рядків формується шляхом виклику dir для об’єкта (за винятком непідтримуваних магічних атрибутів і методів). Доступ до будь-якого атрибута, якого немає в цьому списку, викличе `AttributeError`.

    If spec is an object (rather than a list of strings) then `__class__` returns the class of the spec object. This allows mocks to pass `isinstance()` tests.

  - spec_set: суворіший варіант spec. У разі використання спроба встановити або отримати атрибут у макеті, якого немає в об’єкті, переданому як spec_set, викличе `AttributeError`.

  - side_effect: функція, яка викликається щоразу, коли викликається Mock. Перегляньте атрибут `side_effect`. Корисно для створення винятків або динамічної зміни повернених значень. Функція викликається з тими самими аргументами, що й макет, і якщо вона не повертає `DEFAULT`, значення, що повертається цією функцією, використовується як значення, що повертається.

    Крім того, side_effect може бути класом винятків або екземпляром. У цьому випадку виняток буде викликано під час виклику макета.

    Якщо side_effect є iterable, тоді кожен виклик mock повертатиме наступне значення з iterable.

    Побічний_ефект можна очистити, встановивши для нього значення `None`.

  - return_value: значення, що повертається під час виклику макета. За замовчуванням це новий макет (створений під час першого доступу). Перегляньте атрибут `return_value`.

  - unsafe: By default, accessing any attribute whose name starts with assert, assret, asert, aseert or assrt will raise an `AttributeError`. Passing `unsafe=True` will allow access to these attributes.

    Added in version 3.5.

  - wraps: Елемент для обгортання фіктивного об’єкта. Якщо wraps не `None`, тоді виклик Mock передасть виклик оберненому об’єкту (повертаючи реальний результат). Доступ до атрибутів у макеті поверне об’єкт Mock, який обгортає відповідний атрибут упакованого об’єкта (тому спроба отримати доступ до атрибута, якого не існує, викличе `AttributeError`).

    Якщо макет має явний набір return_value, тоді виклики не передаються до упакованого об’єкта, а замість нього повертається return_value.

  - ім’я: якщо макет має ім’я, воно використовуватиметься у відтворенні макета. Це може бути корисним для налагодження. Ім’я поширюється на дитячі глузування.

  Mocks також можна викликати з довільними ключовими аргументами. Вони використовуватимуться для встановлення атрибутів макета після його створення. Дивіться метод `configure_mock()` для отримання детальної інформації.

  assert_called()

    Стверджуйте, що макет був викликаний принаймні один раз.

        >>> mock = Mock()
        >>> mock.method()
        <Mock name='mock.method()' id='...'>
        >>> mock.method.assert_called()

    Added in version 3.6.

  assert_called_once()

    Стверджуйте, що макет був викликаний рівно один раз.

        >>> mock = Mock()
        >>> mock.method()
        <Mock name='mock.method()' id='...'>
        >>> mock.method.assert_called_once()
        >>> mock.method()
        <Mock name='mock.method()' id='...'>
        >>> mock.method.assert_called_once()
        Traceback (most recent call last):
        ...
        AssertionError: Expected 'method' to have been called once. Called 2 times.
        Calls: [call(), call()].

    Added in version 3.6.

  assert_called_with(*args, **kwargs)

    Цей метод є зручним способом підтвердження того, що останній виклик було зроблено певним чином:

        >>> mock = Mock()
        >>> mock.method(1, 2, 3, test='wow')
        <Mock name='mock.method()' id='...'>
        >>> mock.method.assert_called_with(1, 2, 3, test='wow')

  assert_called_once_with(*args, **kwargs)

    Стверджуйте, що макет був викликаний рівно один раз і цей виклик був із зазначеними аргументами.

        >>> mock = Mock(return_value=None)
        >>> mock('foo', bar='baz')
        >>> mock.assert_called_once_with('foo', bar='baz')
        >>> mock('other', bar='values')
        >>> mock.assert_called_once_with('other', bar='values')
        Traceback (most recent call last):
          ...
        AssertionError: Expected 'mock' to be called once. Called 2 times.
        Calls: [call('foo', bar='baz'), call('other', bar='values')].

  assert_any_call(*args, **kwargs)

    стверджувати, що макет був викликаний із зазначеними аргументами.

    Твердження проходить, якщо макет колись викликався, на відміну від `assert_ called_with()` і `assert_ called_once_with()`, які проходять, лише якщо виклик є останнім, і у випадку `assert_ called_once_with()` це також має бути єдиний виклик.

        >>> mock = Mock(return_value=None)
        >>> mock(1, 2, arg='thing')
        >>> mock('some', 'thing', 'else')
        >>> mock.assert_any_call(1, 2, arg='thing')

  assert_has_calls(calls, any_order=False)

    стверджувати, що макет було викликано за допомогою вказаних викликів. Список `mock_calls` перевіряється на наявність викликів.

    Якщо any_order має значення false, виклики мають бути послідовними. До або після вказаних викликів можуть бути додаткові дзвінки.

    Якщо any_order має значення true, виклики можуть бути в будь-якому порядку, але всі вони мають відображатися в `mock_calls`.

        >>> mock = Mock(return_value=None)
        >>> mock(1)
        >>> mock(2)
        >>> mock(3)
        >>> mock(4)
        >>> calls = [call(2), call(3)]
        >>> mock.assert_has_calls(calls)
        >>> calls = [call(4), call(2), call(3)]
        >>> mock.assert_has_calls(calls, any_order=True)

  assert_not_called()

    Стверджуйте, що макет ніколи не викликався.

        >>> m = Mock()
        >>> m.hello.assert_not_called()
        >>> obj = m.hello()
        >>> m.hello.assert_not_called()
        Traceback (most recent call last):
          ...
        AssertionError: Expected 'hello' to not have been called. Called 1 times.
        Calls: [call()].

    Added in version 3.5.

  reset_mock(*, return_value=False, side_effect=False)

    Метод reset_mock скидає всі атрибути виклику на макетному об’єкті:

        >>> mock = Mock(return_value=None)
        >>> mock('hello')
        >>> mock.called
        True
        >>> mock.reset_mock()
        >>> mock.called
        False

    This can be useful where you want to make a series of assertions that reuse the same object.

    return_value parameter when set to `True` resets `return_value`:

        >>> mock = Mock(return_value=5)
        >>> mock('hello')
        5
        >>> mock.reset_mock(return_value=True)
        >>> mock('hello')
        <Mock name='mock()' id='...'>

    side_effect parameter when set to `True` resets `side_effect`:

        >>> mock = Mock(side_effect=ValueError)
        >>> mock('hello')
        Traceback (most recent call last):
          ...
        ValueError
        >>> mock.reset_mock(side_effect=True)
        >>> mock('hello')
        <Mock name='mock()' id='...'>

    Note that `reset_mock()` doesn’t clear the `return_value`, `side_effect` or any child attributes you have set using normal assignment by default.

    Child mocks are reset as well.

    Змінено в версії 3.6: Added two keyword-only arguments to the reset_mock function.

  mock_add_spec(spec, spec_set=False)

    Додайте специфікацію до макета. spec може бути або об’єктом, або списком рядків. Лише атрибути в специфікації можна отримати як атрибути з макета.

    Якщо spec_set має значення true, можна встановити лише атрибути специфікації.

  attach_mock(mock, attribute)

    Додайте макет як атрибут цього, замінивши його ім’я та батьківський елемент. Виклики вкладеного макету будуть записані в атрибутах `method_calls` і `mock_calls` цього.

  configure_mock(**kwargs)

    Встановіть атрибути макета за допомогою аргументів ключових слів.

    Атрибути плюс значення, що повертаються, і побічні ефекти можуть бути встановлені на дочірніх моделях за допомогою стандартної нотації з крапками та розпакування словника під час виклику методу:

        >>> mock = Mock()
        >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
        >>> mock.configure_mock(**attrs)
        >>> mock.method()
        3
        >>> mock.other()
        Traceback (most recent call last):
          ...
        KeyError

    Те саме можна досягти у виклику конструктора mocks:

        >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
        >>> mock = Mock(some_attribute='eggs', **attrs)
        >>> mock.some_attribute
        'eggs'
        >>> mock.method()
        3
        >>> mock.other()
        Traceback (most recent call last):
          ...
        KeyError

    `configure_mock()` існує, щоб полегшити налаштування після створення макету.

  __dir__()

    Об’єкти `Mock` обмежують результати `dir(some_mock)` корисними результатами. Для макетів із специфікацією це включає всі дозволені атрибути для макету.

    Перегляньте `FILTER_DIR`, щоб дізнатися, що робить це фільтрування та як його вимкнути.

  _get_child_mock(**kw)

    Створіть дочірні макети для атрибутів і повертайте значення. За замовчуванням дочірні макети будуть того самого типу, що й батьківські. Підкласи Mock можуть захотіти перевизначити це, щоб налаштувати спосіб створення дочірніх моків.

    Для макетів, які не підлягають виклику, використовуватиметься варіант, який можна викликати (а не будь-який настроюваний підклас).

  called

    Логічне значення, яке вказує, чи було викликано макетний об’єкт:

        >>> mock = Mock(return_value=None)
        >>> mock.called
        False
        >>> mock()
        >>> mock.called
        True

  call_count

    Ціле число, яке повідомляє вам, скільки разів був викликаний макетний об’єкт:

        >>> mock = Mock(return_value=None)
        >>> mock.call_count
        0
        >>> mock()
        >>> mock()
        >>> mock.call_count
        2

  return_value

    Встановіть це, щоб налаштувати значення, що повертається викликом mock:

        >>> mock = Mock()
        >>> mock.return_value = 'fish'
        >>> mock()
        'fish'

    Типовим значенням, що повертається, є макет об’єкта, і ви можете налаштувати його звичайним способом:

        >>> mock = Mock()
        >>> mock.return_value.attribute = sentinel.Attribute
        >>> mock.return_value()
        <Mock name='mock()()' id='...'>
        >>> mock.return_value.assert_called_with()

    `return_value` також можна встановити в конструкторі:

        >>> mock = Mock(return_value=3)
        >>> mock.return_value
        3
        >>> mock()
        3

  side_effect

    Це може бути або функція, яку потрібно викликати під час виклику макета, ітерація або виняток (клас або екземпляр), який потрібно викликати.

    Якщо ви передаєте функцію, вона буде викликана з тими самими аргументами, що й макет, і якщо функція не повертає синглтон `DEFAULT`, виклик макету поверне те, що повертає функція. Якщо функція повертає `DEFAULT`, макет поверне своє нормальне значення (з `return_value`).

    Якщо ви передаєте ітератор, він використовується для отримання ітератора, який повинен видавати значення під час кожного виклику. Це значення може бути або екземпляром винятку, який буде створено, або значенням, яке буде повернуто викликом mock (обробка `DEFAULT` ідентична функції case).

    Приклад макету, який викликає виняткову ситуацію (для перевірки обробки винятків API):

        >>> mock = Mock()
        >>> mock.side_effect = Exception('Boom!')
        >>> mock()
        Traceback (most recent call last):
          ...
        Exception: Boom!

    Використання `side_effect` для повернення послідовності значень:

        >>> mock = Mock()
        >>> mock.side_effect = [3, 2, 1]
        >>> mock(), mock(), mock()
        (3, 2, 1)

    Використання виклику:

        >>> mock = Mock(return_value=3)
        >>> def side_effect(*args, **kwargs):
        ...     return DEFAULT
        ...
        >>> mock.side_effect = side_effect
        >>> mock()
        3

    `side_effect` можна встановити в конструкторі. Ось приклад, який додає одиницю до значення, з яким викликається макет, і повертає його:

        >>> side_effect = lambda value: value + 1
        >>> mock = Mock(side_effect=side_effect)
        >>> mock(3)
        4
        >>> mock(-8)
        -7

    Встановлення `side_effect` на `None` очищає його:

        >>> m = Mock(side_effect=KeyError, return_value=3)
        >>> m()
        Traceback (most recent call last):
         ...
        KeyError
        >>> m.side_effect = None
        >>> m()
        3

  call_args

    This is either `None` (if the mock hasn’t been called), or the arguments that the mock was last called with. This will be in the form of a tuple: the first member, which can also be accessed through the `args` property, is any positional arguments the mock was called with (or an empty tuple) and the second member, which can also be accessed through the `kwargs` property, is any keyword arguments (or an empty dictionary).

        >>> mock = Mock(return_value=None)
        >>> print(mock.call_args)
        None
        >>> mock()
        >>> mock.call_args
        call()
        >>> mock.call_args == ()
        True
        >>> mock(3, 4)
        >>> mock.call_args
        call(3, 4)
        >>> mock.call_args == ((3, 4),)
        True
        >>> mock.call_args.args
        (3, 4)
        >>> mock.call_args.kwargs
        {}
        >>> mock(3, 4, 5, key='fish', next='w00t!')
        >>> mock.call_args
        call(3, 4, 5, key='fish', next='w00t!')
        >>> mock.call_args.args
        (3, 4, 5)
        >>> mock.call_args.kwargs
        {'key': 'fish', 'next': 'w00t!'}

    `call_args` разом із членами списків `call_args_list`, `method_calls` і `mock_calls` є об’єктами `call`. Це кортежі, тому їх можна розпакувати, щоб отримати окремі аргументи та зробити складніші твердження. Перегляньте виклики як кортежі.

    Змінено в версії 3.8: Додано властивості `args` і `kwargs`.

  call_args_list

    Це список усіх послідовних викликів макетного об’єкта (тому довжина списку — це кількість викликів до нього). До здійснення будь-яких викликів це порожній список. Об’єкт `call` можна використовувати для зручного створення списків викликів для порівняння з `call_args_list`.

        >>> mock = Mock(return_value=None)
        >>> mock()
        >>> mock(3, 4)
        >>> mock(key='fish', next='w00t!')
        >>> mock.call_args_list
        [call(), call(3, 4), call(key='fish', next='w00t!')]
        >>> expected = [(), ((3, 4),), ({'key': 'fish', 'next': 'w00t!'},)]
        >>> mock.call_args_list == expected
        True

    Члени `call_args_list` є об’єктами `call`. Їх можна розпакувати як кортежі, щоб отримати окремі аргументи. Перегляньте виклики як кортежі.

  method_calls

    Крім відстеження викликів самих себе, mocks також відстежують виклики методів і атрибутів, а також їх методів і атрибутів:

        >>> mock = Mock()
        >>> mock.method()
        <Mock name='mock.method()' id='...'>
        >>> mock.property.method.attribute()
        <Mock name='mock.property.method.attribute()' id='...'>
        >>> mock.method_calls
        [call.method(), call.property.method.attribute()]

    Члени `method_calls` є об’єктами `call`. Їх можна розпакувати як кортежі, щоб отримати окремі аргументи. Перегляньте виклики як кортежі.

  mock_calls

    `mock_calls` записує всі виклики макетного об’єкта, його методи, чарівні методи та імітації значення, що повертається.

        >>> mock = MagicMock()
        >>> result = mock(1, 2, 3)
        >>> mock.first(a=3)
        <MagicMock name='mock.first()' id='...'>
        >>> mock.second()
        <MagicMock name='mock.second()' id='...'>
        >>> int(mock)
        1
        >>> result(1)
        <MagicMock name='mock()()' id='...'>
        >>> expected = [call(1, 2, 3), call.first(a=3), call.second(),
        ... call.__int__(), call()(1)]
        >>> mock.mock_calls == expected
        True

    Члени `mock_calls` є об’єктами `call`. Їх можна розпакувати як кортежі, щоб отримати окремі аргументи. Перегляньте виклики як кортежі.

    Примітка

    Спосіб запису `mock_calls` означає, що там, де здійснюються вкладені виклики, параметри викликів предків не записуються, тому порівняння завжди буде рівним:

        >>> mock = MagicMock()
        >>> mock.top(a=3).bottom()
        <MagicMock name='mock.top().bottom()' id='...'>
        >>> mock.mock_calls
        [call.top(a=3), call.top().bottom()]
        >>> mock.mock_calls[-1] == call.top(a=-1).bottom()
        True

  __class__

    Normally the `__class__` attribute of an object will return its type. For a mock object with a `spec`, `__class__` returns the spec class instead. This allows mock objects to pass `isinstance()` tests for the object they are replacing / masquerading as:

        >>> mock = Mock(spec=3)
        >>> isinstance(mock, int)
        True

    `__class__` is assignable to, this allows a mock to pass an `isinstance()` check without forcing you to use a spec:

        >>> mock = Mock()
        >>> mock.__class__ = dict
        >>> isinstance(mock, dict)
        True

class unittest.mock.NonCallableMock(spec=None, wraps=None, name=None, spec_set=None, **kwargs)

  Версія `Mock`, яка не викликається. Параметри конструктора мають те саме значення, що й `Mock`, за винятком return_value і side_effect, які не мають значення для макету, який не викликається.

Mock objects that use a class or an instance as a `spec` or `spec_set` are able to pass `isinstance()` tests:

    >>> mock = Mock(spec=SomeClass)
    >>> isinstance(mock, SomeClass)
    True
    >>> mock = Mock(spec_set=SomeClass())
    >>> isinstance(mock, SomeClass)
    True

Класи `Mock` підтримують методи насміхуватої магії. Дивіться магічні методи для повної інформації.

Імітаційні класи та декоратори `patch()` приймають довільні ключові аргументи для налаштування. Для декораторів `patch()` ключові слова передаються до конструктора макета, який створюється. Ключові аргументи призначені для налаштування атрибутів макета:

    >>> m = MagicMock(attribute=3, other='fish')
    >>> m.attribute
    3
    >>> m.other
    'fish'

Повернене значення та побічний ефект дочірніх імітацій можна встановити таким же чином, використовуючи позначення з крапками. Оскільки ви не можете використовувати імена з крапками безпосередньо у виклику, вам потрібно створити словник і розпакувати його за допомогою `**`:

    >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError}
    >>> mock = Mock(some_attribute='eggs', **attrs)
    >>> mock.some_attribute
    'eggs'
    >>> mock.method()
    3
    >>> mock.other()
    Traceback (most recent call last):
      ...
    KeyError

Викликаний макет, створений за допомогою spec (або spec_set), перевіряє підпис об’єкта специфікації під час зіставлення викликів з макетом. Таким чином, він може відповідати фактичним аргументам виклику незалежно від того, чи були вони передані позиційно чи за назвою:

    >>> def f(a, b, c): pass
    ...
    >>> mock = Mock(spec=f)
    >>> mock(1, 2, c=3)
    <Mock name='mock()' id='140161580456576'>
    >>> mock.assert_called_with(1, 2, 3)
    >>> mock.assert_called_with(a=1, b=2, c=3)

Це стосується `assert_ called_with()`, `assert_ called_once_with()`, `assert_has_calls()` і `assert_any_call()`. Коли Автоматична специфікація, це також застосовуватиметься до викликів методів фіктивного об’єкта.

Змінено в версії 3.4: Додано авторську перевірку підпису на специфіковані та автоматично специфіковані макетні об’єкти.

class unittest.mock.PropertyMock(*args, **kwargs)

  A mock intended to be used as a `property`, or other descriptor, on a class. `PropertyMock` provides `__get__()` and `__set__()` methods so you can specify a return value when it is fetched.

  Отримання екземпляра `PropertyMock` з об’єкта викликає макет без аргументів. Його встановлення викликає макет із встановленим значенням.

      >>> class Foo:
      ...     @property
      ...     def foo(self):
      ...         return 'something'
      ...     @foo.setter
      ...     def foo(self, value):
      ...         pass
      ...
      >>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo:
      ...     mock_foo.return_value = 'mockity-mock'
      ...     this_foo = Foo()
      ...     print(this_foo.foo)
      ...     this_foo.foo = 6
      ...
      mockity-mock
      >>> mock_foo.mock_calls
      [call(), call(6)]

Через те, як зберігаються макетні атрибути, ви не можете безпосередньо прикріпити `PropertyMock` до макетного об’єкта. Замість цього ви можете прикріпити його до об’єкта макетного типу:

    >>> m = MagicMock()
    >>> p = PropertyMock(return_value=3)
    >>> type(m).foo = p
    >>> m.foo
    3
    >>> p.assert_called_once_with()

Застереження

If an `AttributeError` is raised by `PropertyMock`, it will be interpreted as a missing descriptor and `__getattr__()` will be called on the parent mock:

    >>> m = MagicMock()
    >>> no_attribute = PropertyMock(side_effect=AttributeError)
    >>> type(m).my_property = no_attribute
    >>> m.my_property
    <MagicMock name='mock.my_property' id='140165240345424'>

See `__getattr__()` for details.

class unittest.mock.AsyncMock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, **kwargs)

  Асинхронна версія `MagicMock`. Об’єкт `AsyncMock` поводитиметься таким чином, що об’єкт розпізнається як асинхронна функція, а результат виклику є очікуваним.

      >>> mock = AsyncMock()
      >>> inspect.iscoroutinefunction(mock)
      True
      >>> inspect.isawaitable(mock())
      True

  Результатом `mock()` є асинхронна функція, яка матиме результат `side_effect` або `return_value` після очікування:

  - якщо `side_effect` є функцією, асинхронна функція поверне результат цієї функції,

  - якщо `side_effect` є винятком, функція async викличе виняток,

  - якщо `side_effect` є ітерованим, функція async поверне наступне значення ітерованого, однак, якщо послідовність результатів вичерпана, `StopAsyncIteration` викликається негайно,

  - якщо `side_effect` не визначено, функція async поверне значення, визначене `return_value`, отже, за замовчуванням функція async повертає новий об’єкт `AsyncMock`.

  Встановлення специфікації `Mock` або `MagicMock` на асинхронну функцію призведе до повернення об’єкта співпрограми після виклику.

      >>> async def async_func(): pass
      ...
      >>> mock = MagicMock(async_func)
      >>> mock
      <MagicMock spec='function' id='...'>
      >>> mock()
      <coroutine object AsyncMockMixin._mock_call at ...>

  Встановлення специфікації `Mock`, `MagicMock` або `AsyncMock` для класу з асинхронними та синхронними функціями автоматично визначить синхронні функції та встановить їх як `MagicMock` (якщо батьківським макетом є `AsyncMock` або `MagicMock`) або `Mock` (якщо батьківським макетом є `Mock`). Усі асинхронні функції будуть `AsyncMock`.

      >>> class ExampleClass:
      ...     def sync_foo():
      ...         pass
      ...     async def async_foo():
      ...         pass
      ...
      >>> a_mock = AsyncMock(ExampleClass)
      >>> a_mock.sync_foo
      <MagicMock name='mock.sync_foo' id='...'>
      >>> a_mock.async_foo
      <AsyncMock name='mock.async_foo' id='...'>
      >>> mock = Mock(ExampleClass)
      >>> mock.sync_foo
      <Mock name='mock.sync_foo' id='...'>
      >>> mock.async_foo
      <AsyncMock name='mock.async_foo' id='...'>

  Added in version 3.8.

  assert_awaited()

    Стверджуйте, що макету чекали хоча б раз. Зауважте, що це окремо від викликаного об’єкта, необхідно використовувати ключове слово `await`:

        >>> mock = AsyncMock()
        >>> async def main(coroutine_mock):
        ...     await coroutine_mock
        ...
        >>> coroutine_mock = mock()
        >>> mock.called
        True
        >>> mock.assert_awaited()
        Traceback (most recent call last):
        ...
        AssertionError: Expected mock to have been awaited.
        >>> asyncio.run(main(coroutine_mock))
        >>> mock.assert_awaited()

  assert_awaited_once()

    Стверджують, що макет чекали рівно один раз.

        >>> mock = AsyncMock()
        >>> async def main():
        ...     await mock()
        ...
        >>> asyncio.run(main())
        >>> mock.assert_awaited_once()
        >>> asyncio.run(main())
        >>> mock.assert_awaited_once()
        Traceback (most recent call last):
        ...
        AssertionError: Expected mock to have been awaited once. Awaited 2 times.

  assert_awaited_with(*args, **kwargs)

    Підтвердження того, що останнє очікування було з указаними аргументами.

        >>> mock = AsyncMock()
        >>> async def main(*args, **kwargs):
        ...     await mock(*args, **kwargs)
        ...
        >>> asyncio.run(main('foo', bar='bar'))
        >>> mock.assert_awaited_with('foo', bar='bar')
        >>> mock.assert_awaited_with('other')
        Traceback (most recent call last):
        ...
        AssertionError: expected await not found.
        Expected: mock('other')
        Actual: mock('foo', bar='bar')

  assert_awaited_once_with(*args, **kwargs)

    Стверджуйте, що макет очікувався рівно один раз і з вказаними аргументами.

        >>> mock = AsyncMock()
        >>> async def main(*args, **kwargs):
        ...     await mock(*args, **kwargs)
        ...
        >>> asyncio.run(main('foo', bar='bar'))
        >>> mock.assert_awaited_once_with('foo', bar='bar')
        >>> asyncio.run(main('foo', bar='bar'))
        >>> mock.assert_awaited_once_with('foo', bar='bar')
        Traceback (most recent call last):
        ...
        AssertionError: Expected mock to have been awaited once. Awaited 2 times.

  assert_any_await(*args, **kwargs)

    Стверджуйте, що макет коли-небудь був очікуваний із зазначеними аргументами.

        >>> mock = AsyncMock()
        >>> async def main(*args, **kwargs):
        ...     await mock(*args, **kwargs)
        ...
        >>> asyncio.run(main('foo', bar='bar'))
        >>> asyncio.run(main('hello'))
        >>> mock.assert_any_await('foo', bar='bar')
        >>> mock.assert_any_await('other')
        Traceback (most recent call last):
        ...
        AssertionError: mock('other') await not found

  assert_has_awaits(calls, any_order=False)

    Стверджувати, що макет очікувався з указаними викликами. Список `await_args_list` перевіряється на наявність очікувань.

    Якщо any_order має значення false, очікування мають бути послідовними. Можуть бути додаткові виклики до або після вказаних очікувань.

    Якщо any_order має значення true, очікування можуть бути в будь-якому порядку, але всі вони мають відображатися в `await_args_list`.

        >>> mock = AsyncMock()
        >>> async def main(*args, **kwargs):
        ...     await mock(*args, **kwargs)
        ...
        >>> calls = [call("foo"), call("bar")]
        >>> mock.assert_has_awaits(calls)
        Traceback (most recent call last):
        ...
        AssertionError: Awaits not found.
        Expected: [call('foo'), call('bar')]
        Actual: []
        >>> asyncio.run(main('foo'))
        >>> asyncio.run(main('bar'))
        >>> mock.assert_has_awaits(calls)

  assert_not_awaited()

    Стверджують, що макет так і не дочекався.

        >>> mock = AsyncMock()
        >>> mock.assert_not_awaited()

  reset_mock(*args, **kwargs)

    Перегляньте `Mock.reset_mock()`. Також встановлює `await_count` на 0, `await_args` на None і очищає `await_args_list`.

  await_count

    Ціле число, яке відстежує, скільки разів очікувався макетний об’єкт.

        >>> mock = AsyncMock()
        >>> async def main():
        ...     await mock()
        ...
        >>> asyncio.run(main())
        >>> mock.await_count
        1
        >>> asyncio.run(main())
        >>> mock.await_count
        2

  await_args

    Це або `None` (якщо макет не був очікуваний), або аргументи, з якими макет було очікувано востаннє. Функціонує так само, як `Mock.call_args`.

        >>> mock = AsyncMock()
        >>> async def main(*args):
        ...     await mock(*args)
        ...
        >>> mock.await_args
        >>> asyncio.run(main('foo'))
        >>> mock.await_args
        call('foo')
        >>> asyncio.run(main('bar'))
        >>> mock.await_args
        call('bar')

  await_args_list

    Це список усіх очікувань, зроблених для макетного об’єкта в послідовності (тому довжина списку — це кількість разів, коли його очікували). Перш ніж було зроблено будь-які очікування, це порожній список.

        >>> mock = AsyncMock()
        >>> async def main(*args):
        ...     await mock(*args)
        ...
        >>> mock.await_args_list
        []
        >>> asyncio.run(main('foo'))
        >>> mock.await_args_list
        [call('foo')]
        >>> asyncio.run(main('bar'))
        >>> mock.await_args_list
        [call('foo'), call('bar')]

class unittest.mock.ThreadingMock(spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, unsafe=False, *, timeout=UNSET, **kwargs)

  A version of `MagicMock` for multithreading tests. The `ThreadingMock` object provides extra methods to wait for a call to be invoked, rather than assert on it immediately.

  The default timeout is specified by the `timeout` argument, or if unset by the `ThreadingMock.DEFAULT_TIMEOUT` attribute, which defaults to blocking (`None`).

  You can configure the global default timeout by setting `ThreadingMock.DEFAULT_TIMEOUT`.

  wait_until_called(*, timeout=UNSET)

    Waits until the mock is called.

    If a timeout was passed at the creation of the mock or if a timeout argument is passed to this function, the function raises an `AssertionError` if the call is not performed in time.

        >>> mock = ThreadingMock()
        >>> thread = threading.Thread(target=mock)
        >>> thread.start()
        >>> mock.wait_until_called(timeout=1)
        >>> thread.join()

  wait_until_any_call_with(*args, **kwargs)

    Waits until the mock is called with the specified arguments.

    If a timeout was passed at the creation of the mock the function raises an `AssertionError` if the call is not performed in time.

        >>> mock = ThreadingMock()
        >>> thread = threading.Thread(target=mock, args=("arg1", "arg2",), kwargs={"arg": "thing"})
        >>> thread.start()
        >>> mock.wait_until_any_call_with("arg1", "arg2", arg="thing")
        >>> thread.join()

  DEFAULT_TIMEOUT

    Global default timeout in seconds to create instances of `ThreadingMock`.

  Added in version 3.13.

### Дзвінок

Фіктивні об’єкти можна викликати. Виклик поверне значення, встановлене як атрибут `return_value`. Типовим значенням, що повертається, є новий об’єкт Mock; воно створюється під час першого доступу до значення, що повертається (явним чином або шляхом виклику Mock), але воно зберігається й кожного разу повертається те саме.

Виклики, здійснені до об’єкта, будуть записані в такі атрибути, як `call_args` і `call_args_list`.

If `side_effect` is set then it will be called after the call has been recorded, so if `side_effect` raises an exception the call is still recorded.

Найпростіший спосіб змусити макет викликати виняток під час виклику — це зробити `side_effect` класом або екземпляром виключення:

    >>> m = MagicMock(side_effect=IndexError)
    >>> m(1, 2, 3)
    Traceback (most recent call last):
      ...
    IndexError
    >>> m.mock_calls
    [call(1, 2, 3)]
    >>> m.side_effect = KeyError('Bang!')
    >>> m('two', 'three', 'four')
    Traceback (most recent call last):
      ...
    KeyError: 'Bang!'
    >>> m.mock_calls
    [call(1, 2, 3), call('two', 'three', 'four')]

If `side_effect` is a function then whatever that function returns is what calls to the mock return. The `side_effect` function is called with the same arguments as the mock. This allows you to vary the return value of the call dynamically, based on the input:

    >>> def side_effect(value):
    ...     return value + 1
    ...
    >>> m = MagicMock(side_effect=side_effect)
    >>> m(1)
    2
    >>> m(2)
    3
    >>> m.mock_calls
    [call(1), call(2)]

If you want the mock to still return the default return value (a new mock), or any set return value, then there are two ways of doing this. Either return `return_value` from inside `side_effect`, or return `DEFAULT`:

    >>> m = MagicMock()
    >>> def side_effect(*args, **kwargs):
    ...     return m.return_value
    ...
    >>> m.side_effect = side_effect
    >>> m.return_value = 3
    >>> m()
    3
    >>> def side_effect(*args, **kwargs):
    ...     return DEFAULT
    ...
    >>> m.side_effect = side_effect
    >>> m()
    3

To remove a `side_effect`, and return to the default behaviour, set the `side_effect` to `None`:

    >>> m = MagicMock(return_value=6)
    >>> def side_effect(*args, **kwargs):
    ...     return 3
    ...
    >>> m.side_effect = side_effect
    >>> m()
    3
    >>> m.side_effect = None
    >>> m()
    6

The `side_effect` can also be any iterable object. Repeated calls to the mock will return values from the iterable (until the iterable is exhausted and a `StopIteration` is raised):

    >>> m = MagicMock(side_effect=[1, 2, 3])
    >>> m()
    1
    >>> m()
    2
    >>> m()
    3
    >>> m()
    Traceback (most recent call last):
      ...
    StopIteration

Якщо будь-які члени iterable є винятками, вони будуть викликані замість повернення:

    >>> iterable = (33, ValueError, 66)
    >>> m = MagicMock(side_effect=iterable)
    >>> m()
    33
    >>> m()
    Traceback (most recent call last):
     ...
    ValueError
    >>> m()
    66

### Видалення атрибутів

Макетні об’єкти створюють атрибути на вимогу. Це дозволяє їм видавати себе за об’єкти будь-якого типу.

You may want a mock object to return `False` to a `hasattr()` call, or raise an `AttributeError` when an attribute is fetched. You can do this by providing an object as a `spec` for a mock, but that isn’t always convenient.

Ви «блокуєте» атрибути, видаляючи їх. Після видалення доступ до атрибута викличе `AttributeError`.

    >>> mock = MagicMock()
    >>> hasattr(mock, 'm')
    True
    >>> del mock.m
    >>> hasattr(mock, 'm')
    False
    >>> del mock.f
    >>> mock.f
    Traceback (most recent call last):
        ...
    AttributeError: f

### Макетні назви та атрибут name

Оскільки «name» є аргументом конструктора `Mock`, якщо ви хочете, щоб ваш макетний об’єкт мав атрибут «name», ви не можете просто передати його під час створення. Є дві альтернативи. Одним із варіантів є використання `configure_mock()`:

    >>> mock = MagicMock()
    >>> mock.configure_mock(name='my_name')
    >>> mock.name
    'my_name'

Простішим варіантом є просто встановити атрибут «name» після створення макета:

    >>> mock = MagicMock()
    >>> mock.name = "foo"

### Додавання макетів як атрибутів

Коли ви додаєте макет як атрибут іншого макету (або як значення, що повертається), він стає «дочірнім» для цього макету. Виклики дочірнього елемента записуються в атрибутах `method_calls` і `mock_calls` батьківського. Це корисно для конфігурації дочірніх імітацій, а потім прикріплення їх до батьківського, або для прикріплення імітацій до батьківського, який записує всі виклики до нащадків і дозволяє вам робити твердження щодо порядку викликів між імітаціями:

    >>> parent = MagicMock()
    >>> child1 = MagicMock(return_value=None)
    >>> child2 = MagicMock(return_value=None)
    >>> parent.child1 = child1
    >>> parent.child2 = child2
    >>> child1(1)
    >>> child2(2)
    >>> parent.mock_calls
    [call.child1(1), call.child2(2)]

Винятком є випадки, коли макет має назву. Це дозволяє запобігти «батьківству», якщо з якихось причин ви цього не хочете.

    >>> mock = MagicMock()
    >>> not_a_child = MagicMock(name='not-a-child')
    >>> mock.attribute = not_a_child
    >>> mock.attribute()
    <MagicMock name='not-a-child()' id='...'>
    >>> mock.mock_calls
    []

Макети, створені для вас `patch()`, автоматично отримують імена. Щоб приєднати імена до батьківського елемента, ви використовуєте метод `attach_mock()`:

    >>> thing1 = object()
    >>> thing2 = object()
    >>> parent = MagicMock()
    >>> with patch('__main__.thing1', return_value=None) as child1:
    ...     with patch('__main__.thing2', return_value=None) as child2:
    ...         parent.attach_mock(child1, 'child1')
    ...         parent.attach_mock(child2, 'child2')
    ...         child1('one')
    ...         child2('two')
    ...
    >>> parent.mock_calls
    [call.child1('one'), call.child2('two')]

[1]

Єдиний виняток становлять магічні методи та атрибути (ті, що мають на початку та в кінці подвійне підкреслення). Mock не створює їх, а натомість викликає `AttributeError`. Це пояснюється тим, що інтерпретатор часто неявно запитує ці методи і дуже плутається, коли отримує новий об’єкт Mock, коли очікує чарівний метод. Якщо вам потрібна підтримка магічних методів, перегляньте магічні методи.

## Патчери

Декоратори латок використовуються для латання об’єктів лише в межах функції, яку вони декорують. Вони автоматично виконують видалення виправлень за вас, навіть якщо виникають винятки. Усі ці функції також можна використовувати в операторах або як декоратори класів.

### патч

Примітка

Головне — виконати виправлення у правильному просторі імен. Дивіться розділ where to patch.

unittest.mock.patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

  `patch()` діє як декоратор функції, декоратор класу або менеджер контексту. Усередині тіла функції або оператора ціль додається до нового об’єкта. Коли оператор function/with завершує роботу, патч скасовується.

  Якщо new пропущено, ціль замінюється на `AsyncMock`, якщо виправлений об’єкт є асинхронною функцією, або `MagicMock` інакше. Якщо `patch()` використовується як декоратор, а new опущено, створений макет передається як додатковий аргумент до декорованої функції. Якщо `patch()` використовується як менеджер контексту, створений макет повертається менеджером контексту.

  ціль має бути рядком у формі `'package.module.ClassName`. Ціль імпортується, а вказаний об’єкт замінюється на новий об’єкт, тому ціль має бути імпортованою із середовища, з якого ви викликаєте `patch()`. Ціль імпортується під час виконання декорованої функції, а не під час декорування.

  Ключові аргументи spec і spec_set передаються в `MagicMock`, якщо patch створює його для вас.

  Крім того, ви можете передати `spec=True` або `spec_set=True`, що спричиняє передачу латки в об’єкті, який імітується, як об’єкт spec/spec_set.

  new_callable дозволяє вказати інший клас або викликаний об’єкт, який буде викликано для створення нового об’єкта. За замовчуванням `AsyncMock` використовується для асинхронних функцій, а `MagicMock` для решти.

  Більш потужною формою spec є autospec. Якщо ви встановите `autospec=True`, макет буде створено зі специфікацією об’єкта, який замінюється. Усі атрибути макета також матимуть специфікацію відповідного атрибута об’єкта, який замінюється. Методи та функції, які знущаються, перевірятимуть аргументи та викличуть `TypeError`, якщо вони викликані з неправильним підписом. Для моків, які замінюють клас, їх значення, що повертається («екземпляр») матиме ту саму специфікацію, що й клас. Перегляньте функцію `create_autospec()` і Автоматична специфікація.

  Замість `autospec=True` ви можете передати `autospec=some_object`, щоб використовувати довільний об’єкт як специфікацію замість того, що замінюється.

  За замовчуванням `patch()` не зможе замінити атрибути, яких не існує. Якщо ви передаєте `create=True`, а атрибут не існує, patch створить атрибут для вас під час виклику виправленої функції та видалить його знову після завершення виправленої функції. Це корисно для написання тестів щодо атрибутів, які ваш робочий код створює під час виконання. За умовчанням його вимкнено, оскільки це може бути небезпечно. Якщо його ввімкнути, ви можете писати тести проходження проти API, яких насправді не існує!

  Примітка

  Змінено в версії 3.5: Якщо ви виправляєте вбудовані компоненти в модулі, вам не потрібно передавати `create=True`, він буде доданий за замовчуванням.

  Patch can be used as a `TestCase` class decorator. It works by decorating each test method in the class. This reduces the boilerplate code when your test methods share a common patchings set. `patch()` finds tests by looking for method names that start with `patch.TEST_PREFIX`. By default this is `'test'`, which matches the way `unittest` finds tests. You can specify an alternative prefix by setting `patch.TEST_PREFIX`.

  Патч можна використовувати як менеджер контексту за допомогою оператора with. Тут виправлення застосовується до блоку з відступом після оператора with. Якщо ви використовуєте «as», тоді виправлений об’єкт буде прив’язаний до імені після «as»; дуже корисно, якщо `patch()` створює для вас макет об’єкта.

  `patch()` приймає довільні ключові аргументи. Вони будуть передані до `AsyncMock`, якщо виправлений об’єкт є асинхронним, до `MagicMock` інакше або до new_callable, якщо вказано.

  `patch.dict(...)`, `patch.multiple(...)` і `patch.object(...)` доступні для альтернативних варіантів використання.

`patch()` як декоратор функції, створює макет для вас і передає його в декоровану функцію:

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

Виправлення класу замінює клас на екземпляр `MagicMock`. Якщо екземпляр класу створено в тестованому коді, тоді використовуватиметься `return_value` макету.

Якщо екземпляр класу створюється кілька разів, ви можете використовувати `side_effect`, щоб щоразу повертати новий макет. Крім того, ви можете встановити return_value як будь-яке значення.

To configure return values on methods of instances on the patched class you must do this on the `return_value`. For example:

    >>> class Class:
    ...     def method(self):
    ...         pass
    ...
    >>> with patch('__main__.Class') as MockClass:
    ...     instance = MockClass.return_value
    ...     instance.method.return_value = 'foo'
    ...     assert Class() is instance
    ...     assert Class().method() == 'foo'
    ...

Якщо ви використовуєте spec або spec_set і `patch()` замінює клас, тоді значення, що повертається створеним макетом, матиме ту саму специфікацію.

    >>> Original = Class
    >>> patcher = patch('__main__.Class', spec=True)
    >>> MockClass = patcher.start()
    >>> instance = MockClass()
    >>> assert isinstance(instance, Original)
    >>> patcher.stop()

Аргумент new_callable корисний, якщо ви хочете використовувати клас, альтернативний типовому `MagicMock` для створеного макету. Наприклад, якщо ви хочете використовувати `NonCallableMock`:

    >>> thing = object()
    >>> with patch('__main__.thing', new_callable=NonCallableMock) as mock_thing:
    ...     assert thing is mock_thing
    ...     thing()
    ...
    Traceback (most recent call last):
      ...
    TypeError: 'NonCallableMock' object is not callable

Іншим варіантом використання може бути заміна об’єкта екземпляром `io.StringIO`:

    >>> from io import StringIO
    >>> def foo():
    ...     print('Something')
    ...
    >>> @patch('sys.stdout', new_callable=StringIO)
    ... def test(mock_stdout):
    ...     foo()
    ...     assert mock_stdout.getvalue() == 'Something\n'
    ...
    >>> test()

Коли `patch()` створює для вас макет, зазвичай перше, що вам потрібно зробити, це налаштувати макет. Частину цієї конфігурації можна виконати під час виклику patch. Будь-які довільні ключові слова, які ви передаєте у виклик, використовуватимуться для встановлення атрибутів створеного mock:

    >>> patcher = patch('__main__.thing', first='one', second='two')
    >>> mock_thing = patcher.start()
    >>> mock_thing.first
    'one'
    >>> mock_thing.second
    'two'

Крім атрибутів у створених макетних атрибутах, таких як `return_value` і `side_effect`, дочірніх макетів також можна налаштувати. Вони не є синтаксично дійсними для безпосередньої передачі як аргументи ключового слова, але словник із ними як ключами все одно можна розгорнути у виклик `patch()` за допомогою `**`:

    >>> config = {'method.return_value': 3, 'other.side_effect': KeyError}
    >>> patcher = patch('__main__.thing', **config)
    >>> mock_thing = patcher.start()
    >>> mock_thing.method()
    3
    >>> mock_thing.other()
    Traceback (most recent call last):
      ...
    KeyError

За замовчуванням спроба виправити функцію в модулі (або метод чи атрибут у класі), який не існує, закінчиться помилкою з `AttributeError`:

    >>> @patch('sys.non_existing_attribute', 42)
    ... def test():
    ...     assert sys.non_existing_attribute == 42
    ...
    >>> test()
    Traceback (most recent call last):
      ...
    AttributeError: <module 'sys' (built-in)> does not have the attribute 'non_existing_attribute'

але додавання `create=True` до виклику `patch()` змусить попередній приклад працювати належним чином:

    >>> @patch('sys.non_existing_attribute', 42, create=True)
    ... def test(mock_stdout):
    ...     assert sys.non_existing_attribute == 42
    ...
    >>> test()

Змінено в версії 3.8: `patch()` тепер повертає `AsyncMock`, якщо метою є асинхронна функція.

### patch.object

patch.object(target, attribute, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

  заправити названий член (атрибут) на об’єкті (ціль) за допомогою макетного об’єкта.

  `patch.object()` можна використовувати як декоратор, декоратор класу або менеджер контексту. Аргументи new, spec, create, spec_set, autospec і new_callable мають те саме значення, що й для `patch()`. Подібно до `patch()`, `patch.object()` приймає довільні ключові аргументи для налаштування макетного об’єкта, який він створює.

  При використанні як декоратора класу `patch.object()` враховує `patch.TEST_PREFIX` для вибору методів для обгортання.

Ви можете викликати `patch.object()` з трьома або двома аргументами. Форма з трьома аргументами містить об’єкт, який потрібно виправити, ім’я атрибута та об’єкт, на який потрібно замінити атрибут.

Під час виклику з формою з двома аргументами ви пропускаєте об’єкт заміни, і для вас створюється макет, який передається як додатковий аргумент до декорованої функції:

    >>> @patch.object(SomeClass, 'class_method')
    ... def test(mock_method):
    ...     SomeClass.class_method(3)
    ...     mock_method.assert_called_with(3)
    ...
    >>> test()

spec, create та інші аргументи для `patch.object()` мають те саме значення, що й для `patch()`.

### patch.dict

patch.dict(in_dict, values=(), clear=False, **kwargs)

  Patch a dictionary, or dictionary like object, and restore the dictionary to its original state after the test, where the restored dictionary is a copy of the dictionary as it was before the test.

  in_dict може бути словником або контейнером, схожим на відображення. Якщо це відображення, то воно повинно принаймні підтримувати отримання, встановлення та видалення елементів, а також ітерацію по ключах.

  in_dict також може бути рядком, що визначає назву словника, який потім буде отримано шляхом його імпорту.

  values може бути словником значень для встановлення в словнику. значення також можуть бути повторюваними парами `(ключ, значення)`.

  Якщо clear має значення true, словник буде очищено перед встановленням нових значень.

  `patch.dict()` також можна викликати з довільними ключовими аргументами для встановлення значень у словнику.

  Змінено в версії 3.8: `patch.dict()` тепер повертає виправлений словник, коли використовується як менеджер контексту.

`patch.dict()` можна використовувати як контекстний менеджер, декоратор або декоратор класу:

    >>> foo = {}
    >>> @patch.dict(foo, {'newkey': 'newvalue'})
    ... def test():
    ...     assert foo == {'newkey': 'newvalue'}
    ...
    >>> test()
    >>> assert foo == {}

Коли використовується як декоратор класу, `patch.dict()` враховує `patch.TEST_PREFIX` (за замовчуванням `'test'`) для вибору методів для обгортання:

    >>> import os
    >>> import unittest
    >>> from unittest.mock import patch
    >>> @patch.dict('os.environ', {'newkey': 'newvalue'})
    ... class TestSample(unittest.TestCase):
    ...     def test_sample(self):
    ...         self.assertEqual(os.environ['newkey'], 'newvalue')

Якщо ви хочете використовувати інший префікс для свого тесту, ви можете повідомити патчерів про інший префікс, встановивши `patch.TEST_PREFIX`. Докладніше про те, як змінити значення див. TEST_PREFIX.

`patch.dict()` можна використовувати для додавання членів до словника або просто дозволити тесту змінити словник і переконатися, що словник буде відновлено після завершення тесту.

    >>> foo = {}
    >>> with patch.dict(foo, {'newkey': 'newvalue'}) as patched_foo:
    ...     assert foo == {'newkey': 'newvalue'}
    ...     assert patched_foo == {'newkey': 'newvalue'}
    ...     # You can add, update or delete keys of foo (or patched_foo, it's the same dict)
    ...     patched_foo['spam'] = 'eggs'
    ...
    >>> assert foo == {}
    >>> assert patched_foo == {}

    >>> import os
    >>> with patch.dict('os.environ', {'newkey': 'newvalue'}):
    ...     print(os.environ['newkey'])
    ...
    newvalue
    >>> assert 'newkey' not in os.environ

Ключові слова можна використовувати у виклику `patch.dict()` для встановлення значень у словнику:

    >>> mymodule = MagicMock()
    >>> mymodule.function.return_value = 'fish'
    >>> with patch.dict('sys.modules', mymodule=mymodule):
    ...     import mymodule
    ...     mymodule.function('some', 'args')
    ...
    'fish'

`patch.dict()` can be used with dictionary like objects that aren’t actually dictionaries. At the very minimum they must support item getting, setting, deleting and either iteration or membership test. This corresponds to the magic methods `__getitem__()`, `__setitem__()`, `__delitem__()` and either `__iter__()` or `__contains__()`.

    >>> class Container:
    ...     def __init__(self):
    ...         self.values = {}
    ...     def __getitem__(self, name):
    ...         return self.values[name]
    ...     def __setitem__(self, name, value):
    ...         self.values[name] = value
    ...     def __delitem__(self, name):
    ...         del self.values[name]
    ...     def __iter__(self):
    ...         return iter(self.values)
    ...
    >>> thing = Container()
    >>> thing['one'] = 1
    >>> with patch.dict(thing, one=2, two=3):
    ...     assert thing['one'] == 2
    ...     assert thing['two'] == 3
    ...
    >>> assert thing['one'] == 1
    >>> assert list(thing) == ['one']

### patch.multiple

patch.multiple(target, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

  Виконайте кілька патчів за один виклик. Він приймає об’єкт, який потрібно виправити (або як об’єкт, або рядок для отримання об’єкта шляхом імпорту), а також ключові аргументи для патчів:

      with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'):
          ...

  Використовуйте `DEFAULT` як значення, якщо ви хочете, щоб `patch.multiple()` створював для вас макети. У цьому випадку створені макети передаються в декоровану функцію за ключовим словом, а словник повертається, коли `patch.multiple()` використовується як менеджер контексту.

  `patch.multiple()` можна використовувати як декоратор, декоратор класу або менеджер контексту. Аргументи spec, spec_set, create, autospec і new_callable мають те саме значення, що й для `patch()`. Ці аргументи будуть застосовані до всіх патчів, створених `patch.multiple()`.

  При використанні як декоратор класу `patch.multiple()` враховує `patch.TEST_PREFIX` для вибору методів для обгортання.

Якщо ви хочете, щоб `patch.multiple()` створював для вас макети, ви можете використовувати `DEFAULT` як значення. Якщо ви використовуєте `patch.multiple()` як декоратор, тоді створені макети передаються в декоровану функцію за ключовим словом.

    >>> thing = object()
    >>> other = object()

    >>> @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)
    ... def test_function(thing, other):
    ...     assert isinstance(thing, MagicMock)
    ...     assert isinstance(other, MagicMock)
    ...
    >>> test_function()

`patch.multiple()` можна вкладати в інші декоратори `patch`, але розміщувати аргументи, передані ключовим словом після будь-яких стандартних аргументів, створених `patch()`:

    >>> @patch('sys.exit')
    ... @patch.multiple('__main__', thing=DEFAULT, other=DEFAULT)
    ... def test_function(mock_exit, other, thing):
    ...     assert 'other' in repr(other)
    ...     assert 'thing' in repr(thing)
    ...     assert 'exit' in repr(mock_exit)
    ...
    >>> test_function()

Якщо `patch.multiple()` використовується як менеджер контексту, значення, яке повертає менеджер контексту, є словником, у якому створені макети вказуються за назвою:

    >>> with patch.multiple('__main__', thing=DEFAULT, other=DEFAULT) as values:
    ...     assert 'other' in repr(values['other'])
    ...     assert 'thing' in repr(values['thing'])
    ...     assert values['thing'] is thing
    ...     assert values['other'] is other
    ...

### методи латання: запуск і зупинка

All the patchers have `start()` and `stop()` methods. These make it simpler to do patching in `setUp` methods or where you want to do multiple patches without nesting decorators or with statements.

To use them call `patch()`, `patch.object()` or `patch.dict()` as normal and keep a reference to the returned `patcher` object. You can then call `start()` to put the patch in place and `stop()` to undo it.

Якщо ви використовуєте `patch()` для створення макету, його буде повернено викликом `patcher.start`.

    >>> patcher = patch('package.module.ClassName')
    >>> from package import module
    >>> original = module.ClassName
    >>> new_mock = patcher.start()
    >>> assert module.ClassName is not original
    >>> assert module.ClassName is new_mock
    >>> patcher.stop()
    >>> assert module.ClassName is original
    >>> assert module.ClassName is not new_mock

A typical use case for this might be for doing multiple patches in the `setUp` method of a `TestCase`:

    >>> class MyTest(unittest.TestCase):
    ...     def setUp(self):
    ...         self.patcher1 = patch('package.module.Class1')
    ...         self.patcher2 = patch('package.module.Class2')
    ...         self.MockClass1 = self.patcher1.start()
    ...         self.MockClass2 = self.patcher2.start()
    ...
    ...     def tearDown(self):
    ...         self.patcher1.stop()
    ...         self.patcher2.stop()
    ...
    ...     def test_something(self):
    ...         assert package.module.Class1 is self.MockClass1
    ...         assert package.module.Class2 is self.MockClass2
    ...
    >>> MyTest('test_something').run()

Застереження

Якщо ви використовуєте цю техніку, ви повинні переконатися, що виправлення «скасовано», викликавши `stop`. Це може бути складніше, ніж ви могли б подумати, оскільки якщо в `setUp` виникає виняток, `tearDown` не викликається. `unittest.TestCase.addCleanup()` полегшує це:

    >>> class MyTest(unittest.TestCase):
    ...     def setUp(self):
    ...         patcher = patch('package.module.Class')
    ...         self.MockClass = patcher.start()
    ...         self.addCleanup(patcher.stop)
    ...
    ...     def test_something(self):
    ...         assert package.module.Class is self.MockClass
    ...

Як додатковий бонус, вам більше не потрібно зберігати посилання на об’єкт `patcher`.

Також можна зупинити всі запущені латки за допомогою `patch.stopall()`.

patch.stopall()

  Зупинити всі активні патчі. Зупиняє лише патчі, розпочаті з `start`.

### вбудовані виправлення

Ви можете виправляти будь-які вбудовані компоненти в модулі. Наступні приклади патчів вбудовані в `ord()`:

    >>> @patch('__main__.ord')
    ... def test(mock_ord):
    ...     mock_ord.return_value = 101
    ...     print(ord('c'))
    ...
    >>> test()
    101

### TEST_PREFIX

Усі патчери можна використовувати як декоратори класів. При такому використанні вони загортають кожен тестовий метод у клас. Патчери розпізнають методи, які починаються з `'test'`, як методи тестування. Таким же чином `unittest.TestLoader` знаходить тестові методи за замовчуванням.

Можливо, ви хочете використовувати інший префікс для своїх тестів. Ви можете повідомити патчерів про інший префікс, встановивши `patch.TEST_PREFIX`:

    >>> patch.TEST_PREFIX = 'foo'
    >>> value = 3
    >>>
    >>> @patch('__main__.value', 'not three')
    ... class Thing:
    ...     def foo_one(self):
    ...         print(value)
    ...     def foo_two(self):
    ...         print(value)
    ...
    >>>
    >>> Thing().foo_one()
    not three
    >>> Thing().foo_two()
    not three
    >>> value
    3

### Декоратори вкладених патчів

Якщо ви хочете виконати кілька патчів, ви можете просто скласти декоратори.

Ви можете скласти кілька декораторів патчів, використовуючи цей шаблон:

    >>> @patch.object(SomeClass, 'class_method')
    ... @patch.object(SomeClass, 'static_method')
    ... def test(mock1, mock2):
    ...     assert SomeClass.static_method is mock1
    ...     assert SomeClass.class_method is mock2
    ...     SomeClass.static_method('foo')
    ...     SomeClass.class_method('bar')
    ...     return mock1, mock2
    ...
    >>> mock1, mock2 = test()
    >>> mock1.assert_called_once_with('foo')
    >>> mock2.assert_called_once_with('bar')

Зверніть увагу, що декоратори наносяться знизу вгору. Це стандартний спосіб, у який Python застосовує декоратори. Порядок створених макетів, переданих у вашу тестову функцію, відповідає цьому порядку.

### Де латати

`patch()` працює, (тимчасово) змінюючи об’єкт, на який вказує ім’я, на інший. Може бути багато імен, які вказують на будь-який окремий об’єкт, тому, щоб виправлення працювало, ви повинні переконатися, що ви виправляєте ім’я, яке використовує тестована система.

Основний принцип полягає в тому, що ви виправляєте там, де об’єкт переглядається, що не обов’язково є тим самим місцем, де він визначений. Кілька прикладів допоможуть прояснити це.

Уявіть, що у нас є проект, який ми хочемо перевірити з такою структурою:

    a.py
        -> Defines SomeClass

    b.py
        -> from a import SomeClass
        -> some_function instantiates SomeClass

Now we want to test `some_function` but we want to mock out `SomeClass` using `patch()`. The problem is that when we import module b, which we will have to do when it imports `SomeClass` from module a. If we use `patch()` to mock out `a.SomeClass` then it will have no effect on our test; module b already has a reference to the real `SomeClass` and it looks like our patching had no effect.

Головне – виправити `SomeClass` там, де він використовується (або де його шукають). У цьому випадку `some_function` фактично шукатиме `SomeClass` у модулі b, куди ми його імпортували. Виправлення має виглядати:

    @patch('b.SomeClass')

Однак розглянемо альтернативний сценарій, де замість `from a import SomeClass` модуль b виконує `імпорт a`, а `some_function` використовує `a.SomeClass`. Обидві ці форми імпорту поширені. У цьому випадку клас, який ми хочемо виправити, шукається в модулі, тому ми повинні замість цього виправити `a.SomeClass`:

    @patch('a.SomeClass')

### Виправлення дескрипторів і проксі-об’єктів

Both patch and patch.object correctly patch and restore descriptors: class methods, static methods and properties. You should patch these on the class rather than an instance. They also work with some objects that proxy attribute access, like the django settings object.

## Підтримка MagicMock і магічного методу

### Знущальні магічні методи

`Mock` supports mocking the Python protocol methods, also known as «magic methods». This allows mock objects to replace containers or other objects that implement Python protocols.

Оскільки магічні методи шукаються інакше, ніж звичайні методи [2], цю підтримку було реалізовано спеціально. Це означає, що підтримуються лише певні магічні методи. Список підтримуваних включає майже всі з них. Якщо вам бракує чогось, повідомте нам.

Ви імітуєте магічні методи, встановлюючи для методу, який вас цікавить, функцію або імітаційний екземпляр. Якщо ви використовуєте функцію, вона має приймати `self` як перший аргумент [3].

    >>> def __str__(self):
    ...     return 'fooble'
    ...
    >>> mock = Mock()
    >>> mock.__str__ = __str__
    >>> str(mock)
    'fooble'

    >>> mock = Mock()
    >>> mock.__str__ = Mock()
    >>> mock.__str__.return_value = 'fooble'
    >>> str(mock)
    'fooble'

    >>> mock = Mock()
    >>> mock.__iter__ = Mock(return_value=iter([]))
    >>> list(mock)
    []

Одним із варіантів використання цього є знущання над об’єктами, що використовуються як менеджери контексту в операторі `with`:

    >>> mock = Mock()
    >>> mock.__enter__ = Mock(return_value='foo')
    >>> mock.__exit__ = Mock(return_value=False)
    >>> with mock as m:
    ...     assert m == 'foo'
    ...
    >>> mock.__enter__.assert_called_with()
    >>> mock.__exit__.assert_called_with(None, None, None)

Виклики магічних методів не відображаються в `method_calls`, але вони записуються в `mock_calls`.

Примітка

Якщо ви використовуєте аргумент ключового слова spec для створення макета, тоді спроба встановити магічний метод, якого немає в специфікації, призведе до появи `AttributeError`.

Повний список підтримуваних магічних методів:

- `__hash__`, `__sizeof__`, `__repr__` і `__str__`

- `__dir__`, `__format__` і `__subclasses__`

- `__round__`, `__floor__`, `__trunc__` і `__ceil__`

- Порівняння: `__lt__`, `__gt__`, `__le__`, `__ge__`, `__eq__` і `__ne__`

- Методи контейнерів: `__getitem__`, `__setitem__`, `__delitem__`, `__contains__`, `__len__`, `__iter__`, `__reversed__` і `__missing__`

- Менеджер контексту: `__enter__`, `__exit__`, `__aenter__` і `__aexit__`

- Унарні числові методи: `__neg__`, `__pos__` і `__invert__`

- The numeric methods (including right hand and in-place variants): `__add__`, `__sub__`, `__mul__`, `__matmul__`, `__truediv__`, `__floordiv__`, `__mod__`, `__divmod__`, `__lshift__`, `__rshift__`, `__and__`, `__xor__`, `__or__`, and `__pow__`

- Числові методи перетворення: `__complex__`, `__int__`, `__float__` і `__index__`

- Методи дескриптора: `__get__`, `__set__` і `__delete__`

- Травлення: `__reduce__`, `__reduce_ex__`, `__getinitargs__`, `__getnewargs__`, `__getstate__` і `__setstate__`

- Представлення шляху файлової системи: `__fspath__`

- Асинхронні методи ітерації: `__aiter__` і `__anext__`

Змінено в версії 3.8: Додано підтримку для `os.PathLike.__fspath__()`.

Змінено в версії 3.8: Додано підтримку `__aenter__`, `__aexit__`, `__aiter__` і `__anext__`.

Наступні методи існують, але не підтримуються, оскільки вони або використовуються макетом, не можуть бути встановлені динамічно або можуть спричиняти проблеми:

- `__getattr__`, `__setattr__`, `__init__` і `__new__`

- `__prepare__`, `__instancecheck__`, `__subclasscheck__`, `__del__`

### Магічний макет

Є два варіанти `MagicMock`: `MagicMock` і `NonCallableMagicMock`.

class unittest.mock.MagicMock(*args, **kw)

  `MagicMock` is a subclass of `Mock` with default implementations of most of the magic methods. You can use `MagicMock` without having to configure the magic methods yourself.

  Параметри конструктора мають те саме значення, що й для `Mock`.

  Якщо ви використовуєте аргументи spec або spec_set, тоді будуть створені лише магічні методи, які існують у специфікації.

class unittest.mock.NonCallableMagicMock(*args, **kw)

  Версія `MagicMock`, яка не викликається.

  Параметри конструктора мають те саме значення, що й для `MagicMock`, за винятком return_value і side_effect, які не мають значення для макету, який не викликається.

Магічні методи встановлюються за допомогою об’єктів `MagicMock`, тож ви можете налаштувати їх і використовувати у звичайний спосіб:

    >>> mock = MagicMock()
    >>> mock[3] = 'fish'
    >>> mock.__setitem__.assert_called_with(3, 'fish')
    >>> mock.__getitem__.return_value = 'result'
    >>> mock[2]
    'result'

За замовчуванням багато методів протоколу потрібні для повернення об’єктів певного типу. Ці методи попередньо налаштовані зі значенням, що повертається за замовчуванням, тому їх можна використовувати без необхідності робити будь-які дії, якщо ви не зацікавлені у значенні, що повертається. Ви все ще можете встановити значення, що повертається, вручну, якщо ви хочете змінити значення за замовчуванням.

Методи та їх значення за замовчуванням:

- `__lt__`: `NotImplemented`

- `__gt__`: `NotImplemented`

- `__le__`: `NotImplemented`

- `__ge__`: `NotImplemented`

- `__int__`: `1`

- `__contains__`: `False`

- `__len__`: `0`

- `__iter__`: `iter([])`

- `__exit__`: `False`

- `__aexit__`: `False`

- `__complex__`: `1j`

- `__float__`: `1.0`

- `__bool__`: `Правда`

- `__index__`: `1`

- `__hash__`: типовий хеш для макета

- `__str__`: рядок за умовчанням для макета

- `__sizeof__`: розмір за замовчуванням для макету

Наприклад:

    >>> mock = MagicMock()
    >>> int(mock)
    1
    >>> len(mock)
    0
    >>> list(mock)
    []
    >>> object() in mock
    False

The two equality methods, `__eq__()` and `__ne__()`, are special. They do the default equality comparison on identity, using the `side_effect` attribute, unless you change their return value to return something else:

    >>> MagicMock() == 3
    False
    >>> MagicMock() != 3
    True
    >>> mock = MagicMock()
    >>> mock.__eq__.return_value = True
    >>> mock == 3
    True

Повернене значення `MagicMock.__iter__()` може бути будь-яким ітерованим об’єктом і не обов’язково бути ітератором:

    >>> mock = MagicMock()
    >>> mock.__iter__.return_value = ['a', 'b', 'c']
    >>> list(mock)
    ['a', 'b', 'c']
    >>> list(mock)
    ['a', 'b', 'c']

Якщо значення, що повертається, є ітератором, одноразове повторення над ним споживатиме його, а наступні ітерації призведуть до порожнього списку:

    >>> mock.__iter__.return_value = iter(['a', 'b', 'c'])
    >>> list(mock)
    ['a', 'b', 'c']
    >>> list(mock)
    []

У `MagicMock` налаштовано всі підтримувані магічні методи, за винятком деяких незрозумілих і застарілих. Ви все ще можете налаштувати їх, якщо хочете.

Магічні методи, які підтримуються, але не налаштовані за замовчуванням у `MagicMock`:

- `__subclasses__`

- `__dir__`

- `__format__`

- `__get__`, `__set__` і `__delete__`

- `__reversed__` і `__missing__`

- `__reduce__`, `__reduce_ex__`, `__getinitargs__`, `__getnewargs__`, `__getstate__` і `__setstate__`

- `__getformat__`

[2]

Чарівні методи слід шукати в класі, а не в екземплярі. Різні версії Python несумісні щодо застосування цього правила. Підтримувані методи протоколу мають працювати з усіма підтримуваними версіями Python.

[3]

Функція в основному підключена до класу, але кожен екземпляр `Mock` зберігається ізольованим від інших.

## Помічники

### дозорний

unittest.mock.sentinel

  Об’єкт `sentinel` забезпечує зручний спосіб надання унікальних об’єктів для ваших тестів.

  Атрибути створюються на вимогу, коли ви отримуєте доступ до них за іменем. Доступ до того самого атрибуту завжди повертатиме той самий об’єкт. Повернуті об’єкти мають розумне відображення, тому повідомлення про помилку тесту можна прочитати.

  Змінено в версії 3.7: Атрибути `sentinel` тепер зберігають свою ідентичність, коли їх `скопіюють` або `маринують`.

Іноді під час тестування вам потрібно перевірити, чи певний об’єкт передається як аргумент до іншого методу або повертається. Для перевірки цього може бути звичайним створення іменованих дозорних об’єктів. `sentinel` забезпечує зручний спосіб створення та перевірки ідентичності таких об’єктів.

У цьому прикладі ми використовуємо `method` для повернення `sentinel.some_object`:

    >>> real = ProductionClass()
    >>> real.method = Mock(name="method")
    >>> real.method.return_value = sentinel.some_object
    >>> result = real.method()
    >>> assert result is sentinel.some_object
    >>> result
    sentinel.some_object

### ЗА ПРОМОВЧАННЯМ

unittest.mock.DEFAULT

  Об’єкт `DEFAULT` є попередньо створеним дозорним (насправді `sentinel.DEFAULT`). Його можна використовувати функціями `side_effect`, щоб вказати, що потрібно використовувати звичайне повертане значення.

### виклик

unittest.mock.call(*args, **kwargs)

  `call()` — це допоміжний об’єкт для створення простіших тверджень, для порівняння з `call_args`, `call_args_list`, `mock_calls` і `method_calls`. `call()` також можна використовувати з `assert_has_calls()`.

      >>> m = MagicMock(return_value=None)
      >>> m(1, 2, a='foo', b='bar')
      >>> m()
      >>> m.call_args_list == [call(1, 2, a='foo', b='bar'), call()]
      True

call.call_list()

  Для об’єкта виклику, який представляє кілька викликів, `call_list()` повертає список усіх проміжних викликів, а також остаточний виклик.

`call_list` особливо корисний для створення тверджень щодо «ланцюжкових викликів». Зв’язаний виклик — це кілька викликів в одному рядку коду. Це призводить до кількох записів у `mock_calls` на макеті. Побудова послідовності викликів вручну може бути виснажливою.

`call_list()` може побудувати послідовність викликів з одного ланцюжкового виклику:

    >>> m = MagicMock()
    >>> m(1).method(arg='foo').other('bar')(2.0)
    <MagicMock name='mock().method().other()()' id='...'>
    >>> kall = call(1).method(arg='foo').other('bar')(2.0)
    >>> kall.call_list()
    [call(1),
     call().method(arg='foo'),
     call().method().other('bar'),
     call().method().other()(2.0)]
    >>> m.mock_calls == kall.call_list()
    True

Об’єкт `виклику` є або кортежем (позиційні аргументи, аргументи ключового слова) або (ім’я, позиційні аргументи, аргументи ключового слова) залежно від того, як він був створений. Коли ви створюєте їх самостійно, це не особливо цікаво, але об’єкти `call`, які знаходяться в `Mock.call_args`, `Mock.call_args_list` і `Mock.mock_calls` атрибути можна перевірити, щоб отримати окремі аргументи, які вони містять.

Об’єкти `call` у `Mock.call_args` і `Mock.call_args_list` є двома кортежами (позиційні аргументи, аргументи ключового слова), тоді як об’єкти `call` у `Mock.mock_calls` разом із тими, які ви створюєте самостійно, складаються з трьох кортежів (ім’я, позиційні аргументи, аргументи ключового слова).

Ви можете використовувати їх «кортеж», щоб отримати окремі аргументи для більш складного самоаналізу та тверджень. Позиційні аргументи — це кортеж (порожній кортеж, якщо позиційних аргументів немає), а ключові аргументи — це словник:

    >>> m = MagicMock(return_value=None)
    >>> m(1, 2, 3, arg='one', arg2='two')
    >>> kall = m.call_args
    >>> kall.args
    (1, 2, 3)
    >>> kall.kwargs
    {'arg': 'one', 'arg2': 'two'}
    >>> kall.args is kall[0]
    True
    >>> kall.kwargs is kall[1]
    True

    >>> m = MagicMock()
    >>> m.foo(4, 5, 6, arg='two', arg2='three')
    <MagicMock name='mock.foo()' id='...'>
    >>> kall = m.mock_calls[0]
    >>> name, args, kwargs = kall
    >>> name
    'foo'
    >>> args
    (4, 5, 6)
    >>> kwargs
    {'arg': 'two', 'arg2': 'three'}
    >>> name is m.mock_calls[0][0]
    True

### create_autospec

unittest.mock.create_autospec(spec, spec_set=False, instance=False, **kwargs)

  Створіть макет об’єкта, використовуючи інший об’єкт як специфікацію. Атрибути на макеті використовуватимуть відповідний атрибут об’єкта spec як свою специфікацію.

  Аргументи функцій або методів, які висміюються, перевірятимуть, щоб переконатися, що вони викликаються з правильною сигнатурою.

  Якщо spec_set має значення `True`, тоді спроба встановити атрибути, яких не існує в об’єкті специфікації, призведе до появи `AttributeError`.

  Якщо клас використовується як специфікація, тоді значення, що повертається mock (екземпляр класу), матиме ту саму специфікацію. Ви можете використовувати клас як специфікацію для об’єкта екземпляра, передавши `instance=True`. Повернений макет можна буде викликати, лише якщо його екземпляри можна викликати.

  `create_autospec()` також приймає довільні ключові аргументи, які передаються конструктору створеного макету.

Перегляньте Автоматична специфікація для прикладів використання автоматичної специфікації з `create_autospec()` і аргументом autospec для `patch()`.

Змінено в версії 3.8: `create_autospec()` тепер повертає `AsyncMock`, якщо метою є асинхронна функція.

### БУДЬ-ЯКИЙ

unittest.mock.ANY

Іноді вам може знадобитися зробити твердження щодо деяких аргументів у виклику mock, але ви або не дбаєте про деякі з аргументів, або хочете вилучити їх окремо з `call_args` і зробити складнішими твердження на них.

Щоб ігнорувати певні аргументи, ви можете передати об’єкти, порівняння яких дорівнює всему. Виклики `assert_ called_with()` і `assert_ called_once_with()` будуть успішними незалежно від того, що було передано.

    >>> mock = Mock(return_value=None)
    >>> mock('foo', bar=object())
    >>> mock.assert_called_once_with('foo', bar=ANY)

`ANY` також можна використовувати для порівняння зі списками викликів, наприклад `mock_calls`:

    >>> m = MagicMock(return_value=None)
    >>> m(1)
    >>> m(1, 2)
    >>> m(object())
    >>> m.mock_calls == [call(1), call(1, 2), ANY]
    True

`ANY` is not limited to comparisons with call objects and so can also be used in test assertions:

    class TestStringMethods(unittest.TestCase):

        def test_split(self):
            s = 'hello world'
            self.assertEqual(s.split(), ['hello', ANY])

### FILTER_DIR

unittest.mock.FILTER_DIR

`FILTER_DIR` is a module level variable that controls the way mock objects respond to `dir()`. The default is `True`, which uses the filtering described below, to only show useful members. If you dislike this filtering, or need to switch it off for diagnostic purposes, then set `mock.FILTER_DIR = False`.

Якщо фільтрацію ввімкнено, `dir(some_mock)` показує лише корисні атрибути та включатиме будь-які динамічно створені атрибути, які зазвичай не відображаються. Якщо макет було створено за допомогою spec (або autospec, звичайно), тоді відображаються всі атрибути з оригіналу, навіть якщо до них ще не було доступу:

    >>> dir(Mock())
    ['assert_any_call',
     'assert_called',
     'assert_called_once',
     'assert_called_once_with',
     'assert_called_with',
     'assert_has_calls',
     'assert_not_called',
     'attach_mock',
     ...
    >>> from urllib import request
    >>> dir(Mock(spec=request))
    ['AbstractBasicAuthHandler',
     'AbstractDigestAuthHandler',
     'AbstractHTTPHandler',
     'BaseHandler',
     ...

Багато з не дуже корисних (приватних для `Mock`, а не для того, що висміюється) атрибутів підкреслення та подвійного підкреслення з префіксом було відфільтровано з результату виклику `dir()` на `Mock`. Якщо вам не подобається така поведінка, ви можете вимкнути її, встановивши перемикач рівня модуля `FILTER_DIR`:

    >>> from unittest import mock
    >>> mock.FILTER_DIR = False
    >>> dir(mock.Mock())
    ['_NonCallableMock__get_return_value',
     '_NonCallableMock__get_side_effect',
     '_NonCallableMock__return_value_doc',
     '_NonCallableMock__set_return_value',
     '_NonCallableMock__set_side_effect',
     '__call__',
     '__class__',
     ...

Alternatively you can just use `vars(my_mock)` (instance members) and `dir(type(my_mock))` (type members) to bypass the filtering irrespective of `FILTER_DIR`.

### mock_open

unittest.mock.mock_open(mock=None, read_data=None)

  Допоміжна функція для створення макету замість використання `open()`. Це працює для `open()`, що викликається безпосередньо або використовується як контекстний менеджер.

  Аргумент mock є макетним об’єктом для налаштування. Якщо `None` (за замовчуванням), тоді для вас буде створено `MagicMock` з API, обмеженим методами чи атрибутами, доступними для стандартних дескрипторів файлів.

  read_data is a string for the `read()`, `readline()`, and `readlines()` methods of the file handle to return. Calls to those methods will take data from read_data until it is depleted. The mock of these methods is pretty simplistic: every time the mock is called, the read_data is rewound to the start. If you need more control over the data that you are feeding to the tested code you will need to customize this mock for yourself. When that is insufficient, one of the in-memory filesystem packages on PyPI can offer a realistic filesystem for testing.

  Змінено в версії 3.4: Added `readline()` and `readlines()` support. The mock of `read()` changed to consume read_data rather than returning it on each call.

  Змінено в версії 3.5: read_data тепер скидається під час кожного виклику mock.

  Змінено в версії 3.8: Added `__iter__()` to implementation so that iteration (such as in for loops) correctly consumes read_data.

Використання `open()` як контекстного менеджера є чудовим способом переконатися, що ваші дескриптори файлів закриті належним чином, і стає поширеним:

    with open('/some/path', 'w') as f:
        f.write('something')

The issue is that even if you mock out the call to `open()` it is the returned object that is used as a context manager (and has `__enter__()` and `__exit__()` called).

Знущання над контекстними менеджерами за допомогою `MagicMock` є досить поширеним і досить складним, щоб допоміжна функція була корисною.

    >>> m = mock_open()
    >>> with patch('__main__.open', m):
    ...     with open('foo', 'w') as h:
    ...         h.write('some stuff')
    ...
    >>> m.mock_calls
    [call('foo', 'w'),
     call().__enter__(),
     call().write('some stuff'),
     call().__exit__(None, None, None)]
    >>> m.assert_called_once_with('foo', 'w')
    >>> handle = m()
    >>> handle.write.assert_called_once_with('some stuff')

І для читання файлів:

    >>> with patch('__main__.open', mock_open(read_data='bibble')) as m:
    ...     with open('foo') as h:
    ...         result = h.read()
    ...
    >>> m.assert_called_once_with('foo')
    >>> assert result == 'bibble'

### Автоматична специфікація

Autospeccing is based on the existing `spec` feature of mock. It limits the api of mocks to the api of an original object (the spec), but it is recursive (implemented lazily) so that attributes of mocks only have the same api as the attributes of the spec. In addition mocked functions / methods have the same call signature as the original so they raise a `TypeError` if they are called incorrectly.

Перш ніж пояснювати, як працює автоматична специфікація, ось чому вона потрібна.

`Mock` is a very powerful and flexible object, but it suffers from a flaw which is 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.

Змінено в версії 3.5: Before 3.5, tests with a typo in the word assert would silently pass when they should raise an error. You can still achieve this behavior by passing `unsafe=True` to Mock.

Зауважте, що це ще одна причина, чому вам потрібні інтеграційні тести, а також модульні тести. Тестувати все ізольовано — це чудово, але якщо ви не перевірятимете, як ваші пристрої «з’єднані між собою», все ще є багато місця для помилок, які могли виявити тести.

`unittest.mock` already provides a feature to help with this, called speccing. If you use a class or instance as the `spec` for a mock then you can only access attributes on the mock that exist on the real class:

    >>> from urllib import request
    >>> mock = Mock(spec=request.Request)
    >>> mock.assret_called_with  # Intentional typo!
    Traceback (most recent call last):
     ...
    AttributeError: Mock object has no attribute 'assret_called_with'

Специфікація стосується лише самого макету, тому ми все ще маємо ту саму проблему з будь-якими методами на макеті:

    >>> mock.header_items()
    <mock.Mock object at 0x...>
    >>> mock.header_items.assret_called_with()  # Intentional typo!

Автоматична специфікація вирішує цю проблему. Ви можете передати `autospec=True` в `patch()` / `patch.object()` або використати функцію `create_autospec()`, щоб створити макет зі специфікацією. Якщо ви використовуєте аргумент `autospec=True` для `patch()`, тоді об’єкт, який замінюється, використовуватиметься як об’єкт специфікації. Оскільки специфікація виконується «ліниво» (специфікація створюється під час доступу до атрибутів макету), ви можете використовувати її з дуже складними або глибоко вкладеними об’єктами (як-от модулі, які імпортують модулі, які імпортують модулі) без значного зниження продуктивності.

Ось приклад його використання:

    >>> from urllib import request
    >>> patcher = patch('__main__.request', autospec=True)
    >>> mock_request = patcher.start()
    >>> request is mock_request
    True
    >>> mock_request.Request
    <MagicMock name='request.Request' spec='Request' id='...'>

You can see that `request.Request` has a spec. `request.Request` takes two arguments in the constructor (one of which is self). Here’s what happens if we try to call it incorrectly:

    >>> req = request.Request()
    Traceback (most recent call last):
     ...
    TypeError: <lambda>() takes at least 2 arguments (1 given)

Специфікація також стосується екземплярів класів (тобто значення, що повертається specced mocks):

    >>> req = request.Request('foo')
    >>> req
    <NonCallableMagicMock name='request.Request()' spec='Request' id='...'>

`Request` objects are not callable, so the return value of instantiating our mocked out `request.Request` is a non-callable mock. With the spec in place any typos in our asserts will raise the correct error:

    >>> req.add_header('spam', 'eggs')
    <MagicMock name='request.Request().add_header()' id='...'>
    >>> req.add_header.assret_called_with  # Intentional typo!
    Traceback (most recent call last):
     ...
    AttributeError: Mock object has no attribute 'assret_called_with'
    >>> req.add_header.assert_called_with('spam', 'eggs')

У багатьох випадках ви просто зможете додати `autospec=True` до наявних викликів `patch()` і тоді захистити себе від помилок через помилки друку та зміни API.

Окрім використання autospec через `patch()`, існує `create_autospec()` для безпосереднього створення автоспецованих макетів:

    >>> from urllib import request
    >>> mock_request = create_autospec(request)
    >>> mock_request.Request('foo', 'bar')
    <NonCallableMagicMock name='mock.Request()' spec='Request' id='...'>

Однак це не без застережень і обмежень, тому це не типова поведінка. Щоб дізнатися, які атрибути доступні для об’єкта специфікації, autospec має перевірити специфікацію (отримати доступ до атрибутів). Коли ви обходите атрибути на макеті, відповідний обхід оригінального об’єкта відбувається під капотом. Якщо будь-який з ваших специфікованих об’єктів має властивості або дескриптори, які можуть ініціювати виконання коду, можливо, ви не зможете використовувати автоспец. З іншого боку, набагато краще проектувати ваші об’єкти так, щоб самоаналіз був безпечним [4].

A more serious problem is that it is common for instance attributes to be created in the `__init__()` method and not to exist on the class at all. autospec can’t know about any dynamically created attributes and restricts the api to visible attributes.

    >>> class Something:
    ...   def __init__(self):
    ...     self.a = 33
    ...
    >>> with patch('__main__.Something', autospec=True):
    ...   thing = Something()
    ...   thing.a
    ...
    Traceback (most recent call last):
      ...
    AttributeError: Mock object has no attribute 'a'

Існує кілька способів вирішення цієї проблеми. Найпростіший, але не обов’язково найменш дратуючий спосіб – це просто встановити необхідні атрибути на макет після створення. Просто тому, що autospec не дозволяє отримати атрибути, яких немає в специфікації, це не заважає вам налаштувати їх:

    >>> with patch('__main__.Something', autospec=True):
    ...   thing = Something()
    ...   thing.a = 33
    ...

Існує більш агресивна версія як spec, так і autospec, яка не запобігає встановленню неіснуючих атрибутів. Це корисно, якщо ви хочете, щоб ваш код також встановлював дійсні атрибути, але, очевидно, це запобігає цьому конкретному сценарію:

    >>> with patch('__main__.Something', autospec=True, spec_set=True):
    ...   thing = Something()
    ...   thing.a = 33
    ...
    Traceback (most recent call last):
     ...
    AttributeError: Mock object has no attribute 'a'

Probably the best way of solving the problem is to add class attributes as default values for instance members initialised in `__init__()`. Note that if you are only setting default attributes in `__init__()` then providing them via class attributes (shared between instances of course) is faster too. e.g.

    class Something:
        a = 33

Це породжує іншу проблему. Відносно поширеним є надання значення за замовчуванням `None` для членів, які пізніше будуть об’єктом іншого типу. `None` буде марним як специфікація, тому що це не дозволить вам отримати доступ до будь-яких атрибутів або методів на ньому. Оскільки `None` ніколи не буде корисним як специфікація, і, ймовірно, вказує на член, який зазвичай буде іншого типу, autospec не використовує специфікацію для членів, для яких встановлено `None`. Це будуть просто звичайні макети (добре - MagicMocks):

    >>> class Something:
    ...     member = None
    ...
    >>> mock = create_autospec(Something)
    >>> mock.member.foo.bar.baz()
    <MagicMock name='mock.member.foo.bar.baz()' id='...'>

Якщо вам не до вподоби модифікація виробничих класів для додавання значень за замовчуванням, тоді є більше варіантів. Одним із них є просто використання екземпляра як специфікації, а не класу. Інший полягає у створенні підкласу виробничого класу та додаванні стандартних значень до підкласу, не впливаючи на виробничий клас. Обидва вони вимагають використання альтернативного об’єкта як специфікації. На щастя, `patch()` підтримує це — ви можете просто передати альтернативний об’єкт як аргумент autospec:

    >>> class Something:
    ...   def __init__(self):
    ...     self.a = 33
    ...
    >>> class SomethingForTest(Something):
    ...   a = 33
    ...
    >>> p = patch('__main__.Something', autospec=SomethingForTest)
    >>> mock = p.start()
    >>> mock.a
    <NonCallableMagicMock name='Something.a' spec='int' id='...'>

[4]

Це стосується лише класів або вже створених об’єктів. Виклик фіктивного класу для створення фальшивого екземпляра не створює справжній екземпляр. Виконуються лише пошуки атрибутів разом із викликами `dir()`.

### Герметизація макетів

unittest.mock.seal(mock)

  Seal вимкне автоматичне створення макетів під час доступу до атрибута макету, який запечатується, або будь-якого з його атрибутів, які вже є макетами рекурсивно.

  Якщо атрибуту присвоєно макет екземпляра з іменем або специфікацією, він не враховуватиметься в ланцюжку запечатування. Це дозволяє запобігти фіксації пломбою частини фіктивного об’єкта.

      >>> mock = Mock()
      >>> mock.submock.attribute1 = 2
      >>> mock.not_submock = mock.Mock(name="sample_name")
      >>> seal(mock)
      >>> mock.new_attribute  # This will raise AttributeError.
      >>> mock.submock.attribute2  # This will raise AttributeError.
      >>> mock.not_submock.attribute2  # This won't raise.

  Added in version 3.7.

## Order of precedence of `side_effect`, `return_value` and wraps

The order of their precedence is:

1. `side_effect`

2. `return_value`

3. wraps

If all three are set, mock will return the value from `side_effect`, ignoring `return_value` and the wrapped object altogether. If any two are set, the one with the higher precedence will return the value. Regardless of the order of which was set first, the order of precedence remains unchanged.

    >>> from unittest.mock import Mock
    >>> class Order:
    ...     @staticmethod
    ...     def get_value():
    ...         return "third"
    ...
    >>> order_mock = Mock(spec=Order, wraps=Order)
    >>> order_mock.get_value.side_effect = ["first"]
    >>> order_mock.get_value.return_value = "second"
    >>> order_mock.get_value()
    'first'

As `None` is the default value of `side_effect`, if you reassign its value back to `None`, the order of precedence will be checked between `return_value` and the wrapped object, ignoring `side_effect`.

    >>> order_mock.get_value.side_effect = None
    >>> order_mock.get_value()
    'second'

If the value being returned by `side_effect` is `DEFAULT`, it is ignored and the order of precedence moves to the successor to obtain the value to return.

    >>> from unittest.mock import DEFAULT
    >>> order_mock.get_value.side_effect = [DEFAULT]
    >>> order_mock.get_value()
    'second'

When `Mock` wraps an object, the default value of `return_value` will be `DEFAULT`.

    >>> order_mock = Mock(spec=Order, wraps=Order)
    >>> order_mock.return_value
    sentinel.DEFAULT
    >>> order_mock.get_value.return_value
    sentinel.DEFAULT

The order of precedence will ignore this value and it will move to the last successor which is the wrapped object.

As the real call is being made to the wrapped object, creating an instance of this mock will return the real instance of the class. The positional arguments, if any, required by the wrapped object must be passed.

    >>> order_mock_instance = order_mock()
    >>> isinstance(order_mock_instance, Order)
    True
    >>> order_mock_instance.get_value()
    'third'

    >>> order_mock.get_value.return_value = DEFAULT
    >>> order_mock.get_value()
    'third'

    >>> order_mock.get_value.return_value = "second"
    >>> order_mock.get_value()
    'second'

But if you assign `None` to it, this will not be ignored as it is an explicit assignment. So, the order of precedence will not move to the wrapped object.

    >>> order_mock.get_value.return_value = None
    >>> order_mock.get_value() is None
    True

Even if you set all three at once when initializing the mock, the order of precedence remains the same:

    >>> order_mock = Mock(spec=Order, wraps=Order,
    ...                   **{"get_value.side_effect": ["first"],
    ...                      "get_value.return_value": "second"}
    ...                   )
    ...
    >>> order_mock.get_value()
    'first'
    >>> order_mock.get_value.side_effect = None
    >>> order_mock.get_value()
    'second'
    >>> order_mock.get_value.return_value = DEFAULT
    >>> order_mock.get_value()
    'third'

If `side_effect` is exhausted, the order of precedence will not cause a value to be obtained from the successors. Instead, `StopIteration` exception is raised.

    >>> order_mock = Mock(spec=Order, wraps=Order)
    >>> order_mock.get_value.side_effect = ["first side effect value",
    ...                                     "another side effect value"]
    >>> order_mock.get_value.return_value = "second"

    >>> order_mock.get_value()
    'first side effect value'
    >>> order_mock.get_value()
    'another side effect value'

    >>> order_mock.get_value()
    Traceback (most recent call last):
     ...
    StopIteration