Martiusweb / asynctest

Enhance the standard unittest package with features for testing asyncio libraries
https://asynctest.readthedocs.org/
Apache License 2.0
309 stars 41 forks source link

Why MagicMock can't be used in 'await' expression? #140

Open heckad opened 5 years ago

heckad commented 5 years ago

For example, I have the same code

import asynctest

class SomeAsyncClass:
    async def __aenter__(self):
        pass

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        pass

    async def do_something(self):
        pass

async def method_using_SomeAsyncClass():
    async with SomeAsyncClass() as s:
        return await s.do_something()

@asynctest.patch('test.SomeAsyncClass')
async def test_some_test(some_async_class):
    res = await method_using_SomeAsyncClass()

And it fails with error: TypeError: object MagicMock can't be used in 'await' expression. Why and how to fix it?

Martiusweb commented 5 years ago

MagicMock is not awaitable, and the value returned by the call to aenter is unspecified, thus returns a MagicMock.

You need to tell to the mock of SomeAsyncClass what to return in a with statement. In your case, I guess you expect something like "self" thus:

some_async_class.aenter.return_value = some_async_class()

Should work.

On Thu, Aug 29, 2019, 16:22 Kazantcev Andrey notifications@github.com wrote:

For example, I have the same code

import asynctest

class SomeAsyncClass: async def aenter(self): pass

async def __aexit__(self, exc_type, exc_val, exc_tb):
    pass

async def do_something(self):
    pass

async def method_using_SomeAsyncClass(): async with SomeAsyncClass() as s: return await s.do_something()

@asynctest.patch('test.SomeAsyncClass') async def test_some_test(some_async_class): res = await method_using_SomeAsyncClass()

And it fails with error: TypeError: object MagicMock can't be used in 'await' expression. Why and how to fix it?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Martiusweb/asynctest/issues/140?email_source=notifications&email_token=AABPWGBP6OXNYPCFFS4LTTTQG7LQ5A5CNFSM4ISC5BO2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HIG33MQ, or mute the thread https://github.com/notifications/unsubscribe-auth/AABPWGBXDOQ6BQBA47OKX4LQG7LQ5ANCNFSM4ISC5BOQ .

heckad commented 5 years ago

It's not work some_async_class.__aenter__.return_value = some_async_class() The rison of this that some_async_class has been pathed. Also this

@asynctest.patch('test.SomeAsyncClass')
async def test_some_test(some_async_class):
    res = await some_async_class.do_something()

doesn't work. Why MagicMock not pathced methods in SomeAsyncClass?