Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking async call in python 3.5

How do I mock async call from one native coroutine to other one using unittest.mock.patch?

I currently have quite an awkward solution:

class CoroutineMock(MagicMock):     def __await__(self, *args, **kwargs):         future = Future()         future.set_result(self)         result = yield from future         return result 

Then

class TestCoroutines(TestCase):     @patch('some.path', new_callable=CoroutineMock)     def test(self, mock):         some_action()         mock.assert_called_with(1,2,3) 

This works but looks ugly. Is there more pythonic way to do this?

like image 224
Zozz Avatar asked Sep 09 '15 12:09

Zozz


People also ask

How do you call asynchronous in Python?

In asyncio Coroutine can be created by using async keyword before def. To run an async function (coroutine) you have to call it using an Event Loop. Event Loops: You can think of Event Loop as functions to run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses.

How do you call a mock in Python?

How do we mock in Python? Mocking in Python is done by using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .

What is async mock?

Mocking is a fundamental skill in testing. It allows you to avoid testing parts of your code that are outside your control, or to get reliable return values from said code. It also allows you to avoid running code that a test environment is not capable of running.

Can you do async in Python?

Since Python 3.5, it is possible to use asynchronism in your scripts. This evolution allowed the use of new keywords async and await along with the new module asyncio. Async and Await were firstly introduced in C#, in order to structure non-blocking code in a similar fashion as you would write blocking code.


1 Answers

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.

like image 53
SColvin Avatar answered Sep 23 '22 04:09

SColvin