'How to mock an async instance method of a patched class?

(The following code can be run in Jupyter.) I have a class B, which uses class A, needs to be tested.

class A:
    async def f(self):
        pass

class B:
    async def f(self):
        a = A()
        x = await a.f()  # need to be patched/mocked

And I have the following test code. It seems it mocked the class method of A instead of the instance method.

from asyncio import Future
from unittest.mock import MagicMock, Mock, patch

async def test():
    sut = B()
    with patch('__main__.A') as a:  # it's __main__ in Jupyter
        future = Future()
        future.set_result('result')
        a.f = MagicMock(return_value=future)
        await sut.f()

await test()

However, the code got the error of:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
C:\Users\X~1\AppData\Local\Temp\1/ipykernel_36576/3227724090.py in <module>
     20         await sut.f()
     21 
---> 22 await test()

C:\Users\X~1\AppData\Local\Temp\1/ipykernel_36576/3227724090.py in test()
     18         future.set_result('result')
     19         a.f = MagicMock(return_value=future)
---> 20         await sut.f()
     21 
     22 await test()

C:\Users\X~1\AppData\Local\Temp\1/ipykernel_36576/3227724090.py in f(self)
      6     async def f(self):
      7         a = A()
----> 8         x = await a.f()  # need to be patched/mocked
      9 
     10 from asyncio import Future

TypeError: object MagicMock can't be used in 'await' expression


Solution 1:[1]

Need to change

a.f = MagicMock(return_value=future)

to

a().f = MagicMock(return_value=future)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ca9163d9