如何模拟"异步与"声明?

时间:2017-03-24 15:25:24

标签: python-3.x mocking pytest python-asyncio

我试图为使用" async with"的方法编写测试。语句(在这种情况下,aioredis的连接池),我想模拟与redis的连接,但是我无法弄清楚如何。

这是我到目前为止所拥有的:

from asyncio import Future
from unittest.mock import MagicMock

import pytest

# The thing i'm trying to test
async def set_value(redis, value):
    # Do things
    async with redis.get() as conn:
        await conn.set("key", value)

#My Mock classes
class MockRedis():
    def get(self):
        return MockAsyncPool()


class MockAsyncPool(MagicMock):
    async def __aenter__(self):
        conn = MagicMock()
        f = Future()
        f.set_result(True)
        conn.set = MagicMock(return_value=f)
        return conn

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


# The actual test
@pytest.mark.asyncio
async def test_get_token():
    redis = MockRedis()

    token = await set_value(redis, 'something')
    assert token is not None

我用:

运行它
py.test path/to/file.py

我收到此错误:

  

> await conn.set(" key",value)

     

E TypeError:对象无法在等待'等待'表达

1 个答案:

答案 0 :(得分:5)

__aexit__也需要异步(needs to return an awaitable)

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

如果没有异步,则返回None而不是协程,因此会引发错误,因为我创建了一个非常误导的错误消息this issue,指出错误消息需要修复