代码之家  ›  专栏  ›  技术社区  ›  user2023861

Python:如何模拟多次调用的异步方法?

  •  1
  • user2023861  · 技术社区  · 7 年前

    @asyncio.coroutine
    def coroutine_creater(value):
        return value
    

    我是这样用的:

    async def test_test():
        my_mock = Mock(return_value=coroutine_creater(5))
    
        # I call with "await"
        first_call = await my_mock()
        second_call = await my_mock()
    
        assert first_call == 5, 'first call failed'
        assert second_call == 5, 'second call failed'  # this call fails
    

    这样我就可以为异步调用创建模拟。我发现如果我调用async方法两次,这就行不通了。在我的密码里, first_call 像我预期的那样等于5,但是 second_call 等于无。这是怎么回事?如何测试多次调用模拟异步方法的代码?

    0 回复  |  直到 7 年前
        1
  •  0
  •   Lin Du Correcter    5 年前

    你应该设置 side_effect Mock

    side_effect:每当调用Mock时都要调用的函数。请参见“副作用”属性。用于引发异常或动态更改返回值。使用与mock相同的参数调用函数,除非它返回DEFAULT,否则将使用此函数的返回值作为返回值。

    下面的示例使用 pytest-asyncio pytest 模块:

    code_53856568.py

    import asyncio
    
    
    @asyncio.coroutine
    def coroutine_creater(value):
        return value
    

    test_code_53856568.py :

    from unittest.mock import Mock
    from code_53856568 import coroutine_creater
    import pytest
    
    
    @pytest.mark.asyncio
    async def test_test():
        def coroutine_creater_side_effect():
            return coroutine_creater(5)
    
        my_mock = Mock(side_effect=coroutine_creater_side_effect)
    
        first_call = await my_mock()
        second_call = await my_mock()
    
        assert first_call == 5, 'first call failed'
        assert second_call == 5, 'second call failed'
    

    单元测试结果和覆盖率报告:

    (venv) ☁  python-codelab [master] ⚡  coverage run -m pytest /Users/ldu020/workspace/github.com/mrdulin/python-codelab/src/stackoverflow/53856568/test_code_53856568.py && coverage report -m --include="src/*"
    ===================================================================================================================== test session starts =====================================================================================================================
    platform darwin -- Python 3.7.5, pytest-5.3.1, py-1.8.0, pluggy-0.13.1
    rootdir: /Users/ldu020/workspace/github.com/mrdulin/python-codelab
    plugins: asyncio-0.10.0
    collected 1 item                                                                                                                                                                                                                                              
    
    src/stackoverflow/53856568/test_code_53856568.py .                                                                                                                                                                                                      [100%]
    
    ====================================================================================================================== 1 passed in 0.04s ======================================================================================================================
    Name                                               Stmts   Miss  Cover   Missing
    --------------------------------------------------------------------------------
    src/stackoverflow/53856568/code_53856568.py            3      0   100%
    src/stackoverflow/53856568/test_code_53856568.py      11      0   100%
    --------------------------------------------------------------------------------
    TOTAL