bpo-37052: Add examples for mocking async iterators and context manag… · python/cpython@ab74e52 (original) (raw)

Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
12 12
13 13 .. testsetup::
14 14
15 + import asyncio
15 16 import unittest
16 17 from unittest.mock import Mock, MagicMock, patch, call, sentinel
17 18
@@ -276,6 +277,44 @@ function returns is what the call returns:
276 277 2
277 278
278 279
280 +Mocking asynchronous iterators
281 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282 +
283 +Since Python 3.8, ``MagicMock`` has support to mock :ref:`async-iterators`
284 +through ``__aiter__``. The :attr:`~Mock.return_value` attribute of ``__aiter__``
285 +can be used to set the return values to be used for iteration.
286 +
287 + >>> mock = MagicMock()
288 + >>> mock.__aiter__.return_value = [1, 2, 3]
289 + >>> async def main():
290 + ... return [i async for i in mock]
291 + >>> asyncio.run(main())
292 +[1, 2, 3]
293 +
294 +
295 +Mocking asynchronous context manager
296 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
297 +
298 +Since Python 3.8, ``MagicMock`` has support to mock
299 +:ref:`async-context-managers` through ``__aenter__`` and ``__aexit__``. The
300 +return value of ``__aenter__`` is an :class:`AsyncMock`.
301 +
302 + >>> class AsyncContextManager:
303 + ...
304 + ... async def __aenter__(self):
305 + ... return self
306 + ...
307 + ... async def __aexit__(self):
308 + ... pass
309 + >>> mock_instance = MagicMock(AsyncContextManager())
310 + >>> async def main():
311 + ... async with mock_instance as result:
312 + ... pass
313 + >>> asyncio.run(main())
314 + >>> mock_instance.__aenter__.assert_called_once()
315 + >>> mock_instance.__aexit__.assert_called_once()
316 +
317 +
279 318 Creating a Mock from an Existing Object
280 319 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
281 320