title: How to mock aiohttp.client.ClientSession.get async context manager
body: <p>I have some troubles with mocking aiohttp.client.ClientSession.get context manager. I found some articles and here is one example that seems was working: <a href="http://pfertyk.me/2017/06/testing-asynchronous-context-managers-in-python/" rel="noreferrer">article 1</a></p>
  
  <p>So my code that I want to test:</p>
  
  <p><strong>async_app.py</strong></p>
  
  <pre><code>import random
  from aiohttp.client import ClientSession
  
  async def get_random_photo_url():
      while True:
          async with ClientSession() as session:
              async with session.get('random.photos') as resp:
                  json = await resp.json()
          photos = json['photos']
          if not photos:
              continue
          return random.choice(photos)['img_src']
  </code></pre>
  
  <p>And test:</p>
  
  <p><strong>test_async_app.py</strong></p>
  
  <pre><code>from asynctest import CoroutineMock, MagicMock, patch
  
  from asynctest import TestCase as TestCaseAsync
  
  from async_app import get_random_photo_url
  
  
  class AsyncContextManagerMock(MagicMock):
      async def __aenter__(self):
          return self.aenter
  
      async def __aexit__(self, *args):
          pass
  
  class TestAsyncExample(TestCaseAsync):
      @patch('aiohttp.client.ClientSession.get', new_callable=AsyncContextManagerMock)
      async def test_call_api_again_if_photos_not_found(self, mock_get):
          mock_get.return_value.aenter.json = CoroutineMock(side_effect=[{'photos': []},
                                                                         {'photos': [{'img_src': 'a.jpg'}]}])
  
          image_url = await get_random_photo_url()
  
          assert mock_get.call_count == 2
          assert mock_get.return_value.aenter.json.call_count == 2
          assert image_url == 'a.jpg'
  </code></pre>
  
  <p>When I'm running test, I'm getting an error:</p>
  
  <pre><code>(test-0zFWLpVX) ➜  test python -m unittest test_async_app.py -v
  test_call_api_again_if_photos_not_found (test_async_app.TestAsyncExample) ... ERROR
  
  ======================================================================
  ERROR: test_call_api_again_if_photos_not_found (test_async_app.TestAsyncExample)
  ----------------------------------------------------------------------
  Traceback (most recent call last):
    File "/home/kamyanskiy/.local/share/virtualenvs/test-0zFWLpVX/lib/python3.6/site-packages/asynctest/case.py", line 294, in run
      self._run_test_method(testMethod)
    File "/home/kamyanskiy/.local/share/virtualenvs/test-0zFWLpVX/lib/python3.6/site-packages/asynctest/case.py", line 351, in _run_test_method
      self.loop.run_until_complete(result)
    File "/home/kamyanskiy/.local/share/virtualenvs/test-0zFWLpVX/lib/python3.6/site-packages/asynctest/case.py", line 221, in wrapper
      return method(*args, **kwargs)
    File "/usr/lib/python3.6/asyncio/base_events.py", line 467, in run_until_complete
      return future.result()
    File "/home/kamyanskiy/.local/share/virtualenvs/test-0zFWLpVX/lib/python3.6/site-packages/asynctest/_awaitable.py", line 21, in wrapper
      return await coroutine(*args, **kwargs)
    File "/home/kamyanskiy/.local/share/virtualenvs/test-0zFWLpVX/lib/python3.6/site-packages/asynctest/mock.py", line 588, in __next__
      return self.gen.send(None)
    File "/home/kamyanskiy/work/test/test_async_app.py", line 23, in test_call_api_again_if_photos_not_found
      image_url = await get_random_photo_url()
    File "/home/kamyanskiy/work/test/async_app.py", line 9, in get_random_photo_url
      json = await resp.json()
  TypeError: object MagicMock can't be used in 'await' expression
  
  ----------------------------------------------------------------------
  Ran 1 test in 0.003s
  
  FAILED (errors=1)
  </code></pre>
  
  <p>So I've tried to debug - here is what I can see:</p>
  
  <pre><code>&gt; /home/kamyanskiy/work/test/async_app.py(10)get_random_photo_url()
        9                 import ipdb; ipdb.set_trace()
  ---&gt; 10                 json = await resp.json()
       11         photos = json['photos']
  
  ipdb&gt; resp.__aenter__()
  &lt;generator object CoroutineMock._mock_call.&lt;locals&gt;.&lt;lambda&gt; at 0x7effad980048&gt;
  ipdb&gt; resp.aenter
  &lt;MagicMock name='get().__aenter__().aenter' id='139636643357584'&gt;
  ipdb&gt; resp.__aenter__().json()
  *** AttributeError: 'generator' object has no attribute 'json'
  ipdb&gt; resp.__aenter__()
  &lt;generator object CoroutineMock._mock_call.&lt;locals&gt;.&lt;lambda&gt; at 0x7effad912468&gt;
  ipdb&gt; resp.json()
  &lt;MagicMock name='get().__aenter__().json()' id='139636593767928'&gt;
  ipdb&gt; session
  &lt;aiohttp.client.ClientSession object at 0x7effb15548d0&gt;
  ipdb&gt; next(resp.__aenter__())
  TypeError: object MagicMock can't be used in 'await' expression
  </code></pre>
  
  <p>So what is proper way to mock async context manager ?</p>