在python 3.5中模拟异步调用

2024-10-06 12:35:05 发布

您现在位置:Python中文网/ 问答频道 /正文

如何使用unittest.mock.patch模拟从一个本机协程到另一个本机协程的异步调用

我目前有一个相当尴尬的解决方案:

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

然后

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

这可以用,但看起来很难看。有没有更像Python的方法


Tags: selfdefargsfuturesomeunittestresult解决方案
3条回答

解决方案其实很简单: 我只需要将mock的__call__方法转换为协同程序:

class AsyncMock(MagicMock):
    async def __call__(self, *args, **kwargs):
        return super(AsyncMock, self).__call__(*args, **kwargs)

这非常有效,当调用mock时,代码接收本机协同路由

用法示例:

@mock.patch('my.path.asyncio.sleep', new_callable=AsyncMock)
def test_stuff(sleep):
    # code

基于@scolvin answer,我创建了这个(imo)更干净的方式:

import asyncio

def async_return(result):
    f = asyncio.Future()
    f.set_result(result)
    return f

就是这样,只需在想要异步的任何返回周围使用它,如

mock = MagicMock(return_value=async_return("Example return"))
await mock()

每个人都缺少最简单、最清晰的解决方案:

@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)

记住,一个协同程序可以被看作是一个函数,它保证返回一个未来,而这个未来可以被期待

相关问题 更多 >