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

时间:2018-12-19 17:38:53

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

我有一种方法可用于测试Python(3.6)中的异步代码:

my_function <- function(A,B,C,D,E) {
  return(sapply(c(A,B,C,D,E),function(x){
    if(x %in% c(A,E)) return(paste0(x,"foo"))
    if(x %in% c(B,C,D)) return(paste0(x,"bar"))
  }))
}

我这样使用它:

@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 等于5,但first_call等于无。这里发生了什么?如何测试多次调用Mock异步方法的代码?

1 个答案:

答案 0 :(得分:0)

您应该为side_effect设置Mock参数。

side_effect:每当调用Mock时都要调用的函数。请参阅side_effect属性。对于引发异常或动态更改返回值很有用。该函数使用与模拟相同的参数进行调用,除非返回DEFAULT,否则将此函数的返回值用作返回值。

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

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