classification
Title: Add async magic method support to unittest.mock.Mock
Type: enhancement Stage: test needed
Components: Library (Lib) Versions: Python 3.7, Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, brett.cannon, michael.foord, rbcollins, tsutsumi, txomon
Priority: normal Keywords:

Created on 2016-03-01 22:51 by brett.cannon, last changed 2017-02-14 09:38 by berker.peksag.

Messages (5)
msg261092 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2016-03-01 22:51
Mock doesn't support stuff like __aexit__ which means you can't mock out something like an async context manager.
msg267338 - (view) Author: Yusuke Tsutsumi (tsutsumi) * Date: 2016-06-04 22:46
I'm interested in taking this on. I'm considering for this approach, creating a new MagicProxy class specifically for async, and assigning __aexit__ and __aenter__ to those.

The __call__ method itself has to be detected as asynchronous, and I don't believe it's possible for a __call__ to behave appropriately for both asynchronous and synchronous cases.
msg267479 - (view) Author: Yusuke Tsutsumi (tsutsumi) * Date: 2016-06-05 21:51
Taking a look at the code, this may require a bit more discussion.

Mock's classes create copies of themselves when an attribute is accessed. As such, I can't just add __aexit__ and have it generate a different mock type entirely, unless I know exactly what an async variant of this mock is.

If there was a way to specifically provide a function for asynchronous situations, like __acall__, that would make this a lot easier as well.

Anyway, my proposal now is:

create new classes MockAsync and MagicMockAsync, and have MockAsync and MagicMockAsync implement the __aexit__ and __aenter__ methods.

How is that as an approach?
msg267569 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2016-06-06 22:57
There's also __aiter__, but it's semantics might be changing (issue #27243).

Robert or Michael, any opinions on Yusuke's proposal?
msg283657 - (view) Author: Javier Domingo (txomon) Date: 2016-12-20 00:22
I found this while trying to test an async context manager. This is a critical feature to enable migrations to async code, as the impossibility to test something properly is not acceptable in many environments.

Implementing it in a way that __call__ returns an object capable of being coroutine or normal function would avoid having to implement Async specific Mocks, wouldn't it? I am not too confident, but would it be doable to have an implementation that depends on whether _is_coroutine is accessed or not?

I don't like it, but I really don't like the fact that we need to patch different all the methods depending on whether they are coroutine or not.

Obviously, having the __acall__ method would really help solving this issue.
History
Date User Action Args
2017-02-14 09:38:38berker.peksagsetnosy: + berker.peksag

versions: + Python 3.7
2016-12-20 00:22:47txomonsetnosy: + txomon
messages: + msg283657
2016-06-06 22:57:03brett.cannonsetnosy: + rbcollins
messages: + msg267569
2016-06-05 21:51:27tsutsumisetmessages: + msg267479
2016-06-04 22:46:43tsutsumisetnosy: + tsutsumi
messages: + msg267338
2016-03-01 22:51:46brett.cannoncreate