Mocking async call in python 3.5
Solution 1:
The solution was actually quite simple:
I just needed to convert __call__
method of mock into coroutine:
class AsyncMock(MagicMock):
async def __call__(self, *args, **kwargs):
return super(AsyncMock, self).__call__(*args, **kwargs)
This works perfectly, when mock is called, code receives native coroutine
Example usage:
@mock.patch('my.path.asyncio.sleep', new_callable=AsyncMock)
def test_stuff(sleep):
# code
Solution 2:
Everyone's missing what's probably the simplest and clearest solution:
@patch('some.path')
def test(self, mock):
f = asyncio.Future()
f.set_result('whatever result you want')
process_smtp_message.return_value = f
mock.assert_called_with(1, 2, 3)
remember a coroutine can be thought of as just a function which is guaranteed to return a future which can, in turn be awaited.
Solution 3:
Based on @scolvin answer I created this (imo) cleaner way:
import asyncio
def async_return(result):
f = asyncio.Future()
f.set_result(result)
return f
That's it, just use it around whatever return you want to be async, as in
mock = MagicMock(return_value=async_return("Example return"))
await mock()