bpo-26467: Adds AsyncMock for asyncio Mock library support (GH-9296) · python/cpython@77b3b77

@@ -201,9 +201,11 @@ The Mock Class

201201202202

.. testsetup::

203203204+

import asyncio

205+

import inspect

204206

import unittest

205207

from unittest.mock import sentinel, DEFAULT, ANY

206-

from unittest.mock import patch, call, Mock, MagicMock, PropertyMock

208+

from unittest.mock import patch, call, Mock, MagicMock, PropertyMock, AsyncMock

207209

from unittest.mock import mock_open

208210209211

:class:`Mock` is a flexible mock object intended to replace the use of stubs and

@@ -851,6 +853,217 @@ object::

851853

>>> p.assert_called_once_with()

852854853855856+

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

857+858+

An asynchronous version of :class:`Mock`. The :class:`AsyncMock` object will

859+

behave so the object is recognized as an async function, and the result of a

860+

call is an awaitable.

861+862+

>>> mock = AsyncMock()

863+

>>> asyncio.iscoroutinefunction(mock)

864+

True

865+

>>> inspect.isawaitable(mock())

866+

True

867+868+

The result of ``mock()`` is an async function which will have the outcome

869+

of ``side_effect`` or ``return_value``:

870+871+

- if ``side_effect`` is a function, the async function will return the

872+

result of that function,

873+

- if ``side_effect`` is an exception, the async function will raise the

874+

exception,

875+

- if ``side_effect`` is an iterable, the async function will return the

876+

next value of the iterable, however, if the sequence of result is

877+

exhausted, ``StopIteration`` is raised immediately,

878+

- if ``side_effect`` is not defined, the async function will return the

879+

value defined by ``return_value``, hence, by default, the async function

880+

returns a new :class:`AsyncMock` object.

881+882+883+

Setting the *spec* of a :class:`Mock` or :class:`MagicMock` to an async function

884+

will result in a coroutine object being returned after calling.

885+886+

>>> async def async_func(): pass

887+

...

888+

>>> mock = MagicMock(async_func)

889+

>>> mock

890+

<MagicMock spec='function' id='...'>

891+

>>> mock()

892+

<coroutine object AsyncMockMixin._mock_call at ...>

893+894+

.. method:: assert_awaited()

895+896+

Assert that the mock was awaited at least once.

897+898+

>>> mock = AsyncMock()

899+

>>> async def main():

900+

... await mock()

901+

...

902+

>>> asyncio.run(main())

903+

>>> mock.assert_awaited()

904+

>>> mock_2 = AsyncMock()

905+

>>> mock_2.assert_awaited()

906+

Traceback (most recent call last):

907+

...

908+

AssertionError: Expected mock to have been awaited.

909+910+

.. method:: assert_awaited_once()

911+912+

Assert that the mock was awaited exactly once.

913+914+

>>> mock = AsyncMock()

915+

>>> async def main():

916+

... await mock()

917+

...

918+

>>> asyncio.run(main())

919+

>>> mock.assert_awaited_once()

920+

>>> asyncio.run(main())

921+

>>> mock.method.assert_awaited_once()

922+

Traceback (most recent call last):

923+

...

924+

AssertionError: Expected mock to have been awaited once. Awaited 2 times.

925+926+

.. method:: assert_awaited_with(*args, **kwargs)

927+928+

Assert that the last await was with the specified arguments.

929+930+

>>> mock = AsyncMock()

931+

>>> async def main(*args, **kwargs):

932+

... await mock(*args, **kwargs)

933+

...

934+

>>> asyncio.run(main('foo', bar='bar'))

935+

>>> mock.assert_awaited_with('foo', bar='bar')

936+

>>> mock.assert_awaited_with('other')

937+

Traceback (most recent call last):

938+

...

939+

AssertionError: expected call not found.

940+

Expected: mock('other')

941+

Actual: mock('foo', bar='bar')

942+943+

.. method:: assert_awaited_once_with(*args, **kwargs)

944+945+

Assert that the mock was awaited exactly once and with the specified

946+

arguments.

947+948+

>>> mock = AsyncMock()

949+

>>> async def main(*args, **kwargs):

950+

... await mock(*args, **kwargs)

951+

...

952+

>>> asyncio.run(main('foo', bar='bar'))

953+

>>> mock.assert_awaited_once_with('foo', bar='bar')

954+

>>> asyncio.run(main('foo', bar='bar'))

955+

>>> mock.assert_awaited_once_with('foo', bar='bar')

956+

Traceback (most recent call last):

957+

...

958+

AssertionError: Expected mock to have been awaited once. Awaited 2 times.

959+960+

.. method:: assert_any_await(*args, **kwargs)

961+962+

Assert the mock has ever been awaited with the specified arguments.

963+964+

>>> mock = AsyncMock()

965+

>>> async def main(*args, **kwargs):

966+

... await mock(*args, **kwargs)

967+

...

968+

>>> asyncio.run(main('foo', bar='bar'))

969+

>>> asyncio.run(main('hello'))

970+

>>> mock.assert_any_await('foo', bar='bar')

971+

>>> mock.assert_any_await('other')

972+

Traceback (most recent call last):

973+

...

974+

AssertionError: mock('other') await not found

975+976+

.. method:: assert_has_awaits(calls, any_order=False)

977+978+

Assert the mock has been awaited with the specified calls.

979+

The :attr:`await_args_list` list is checked for the awaits.

980+981+

If *any_order* is False (the default) then the awaits must be

982+

sequential. There can be extra calls before or after the

983+

specified awaits.

984+985+

If *any_order* is True then the awaits can be in any order, but

986+

they must all appear in :attr:`await_args_list`.

987+988+

>>> mock = AsyncMock()

989+

>>> async def main(*args, **kwargs):

990+

... await mock(*args, **kwargs)

991+

...

992+

>>> calls = [call("foo"), call("bar")]

993+

>>> mock.assert_has_calls(calls)

994+

Traceback (most recent call last):

995+

...

996+

AssertionError: Calls not found.

997+

Expected: [call('foo'), call('bar')]

998+

>>> asyncio.run(main('foo'))

999+

>>> asyncio.run(main('bar'))

1000+

>>> mock.assert_has_calls(calls)

1001+1002+

.. method:: assert_not_awaited()

1003+1004+

Assert that the mock was never awaited.

1005+1006+

>>> mock = AsyncMock()

1007+

>>> mock.assert_not_awaited()

1008+1009+

.. method:: reset_mock(*args, **kwargs)

1010+1011+

See :func:`Mock.reset_mock`. Also sets :attr:`await_count` to 0,

1012+

:attr:`await_args` to None, and clears the :attr:`await_args_list`.

1013+1014+

.. attribute:: await_count

1015+1016+

An integer keeping track of how many times the mock object has been awaited.

1017+1018+

>>> mock = AsyncMock()

1019+

>>> async def main():

1020+

... await mock()

1021+

...

1022+

>>> asyncio.run(main())

1023+

>>> mock.await_count

1024+

1

1025+

>>> asyncio.run(main())

1026+

>>> mock.await_count

1027+

2

1028+1029+

.. attribute:: await_args

1030+1031+

This is either ``None`` (if the mock hasn’t been awaited), or the arguments that

1032+

the mock was last awaited with. Functions the same as :attr:`Mock.call_args`.

1033+1034+

>>> mock = AsyncMock()

1035+

>>> async def main(*args):

1036+

... await mock(*args)

1037+

...

1038+

>>> mock.await_args

1039+

>>> asyncio.run(main('foo'))

1040+

>>> mock.await_args

1041+

call('foo')

1042+

>>> asyncio.run(main('bar'))

1043+

>>> mock.await_args

1044+

call('bar')

1045+1046+1047+

.. attribute:: await_args_list

1048+1049+

This is a list of all the awaits made to the mock object in sequence (so the

1050+

length of the list is the number of times it has been awaited). Before any

1051+

awaits have been made it is an empty list.

1052+1053+

>>> mock = AsyncMock()

1054+

>>> async def main(*args):

1055+

... await mock(*args)

1056+

...

1057+

>>> mock.await_args_list

1058+

[]

1059+

>>> asyncio.run(main('foo'))

1060+

>>> mock.await_args_list

1061+

[call('foo')]

1062+

>>> asyncio.run(main('bar'))

1063+

>>> mock.await_args_list

1064+

[call('foo'), call('bar')]

1065+1066+8541067

Calling

8551068

~~~~~~~

8561069