python - 如何在Python中进行参数匹配、捕获

标签 python methods mocking matching argument-passing

我试图了解如何在进行模拟方法参数匹配和参数捕获时模拟 python 外部依赖项。

1)参数匹配:

class ExternalDep(object):
    def do_heavy_calc(self, anInput):
        return 3

class Client(object):
    def __init__(self, aDep):
        self._dep = aDep

    def invokeMe(self, aStrVal):
        sum = self._dep.do_heavy_calc(aStrVal)
        aNewStrVal = 'new_' + aStrVal
        sum += self._dep.do_heavy_calc(aNewStrVal)

class ClientTest(unittest.TestCase):
    self.mockDep = MagicMock(name='mockExternalDep', spec_set=ExternalDep)
    ###
    self.mockDep.do_heavy_calc.return_value = 5 
    ### this will be called twice regardless of what parameters are used
    ### in mockito-python, it is possible to create two diff mocks (by param),like
    ###
    ### when(self.mockDep).do_heavy_calc('A').thenReturn(7)
    ### when(self.mockDep).do_heavy_calc('new_A').thenReturn(11)
    ###
    ### QUESTION: how could I archive the same result in MagicMock?

    def setUp(self):
        self.cut = Client(self.mockDep)

    def test_invokeMe(self):
        capturedResult = self.cut.invokeMe('A')
        self.assertEqual(capturedResult, 10, 'Unexpected sum')
        # self.assertEqual(capturedResult, 18, 'Two Stubs did not execute')

2) 参数捕获 我无法在 MagicMock 或 mockito-python 上找到好的文档或示例来适应以下模拟场景:

class ExternalDep(object):
    def save_out(self, anInput):
        return 17

class Client(object):
    def __init__(self, aDep):
        self._dep = aDep

    def create(self, aStrVal):
        aNewStrVal = 'new_' + aStrVal if aStrVal.startswith('a')
        self._dep.save_out(aNewStrVal)

class ClientTest(unittest.TestCase):
    self.mockDep = MagicMock(name='mockExternalDep', spec_set=ExternalDep)
    ###
    self.mockDep.save_out.return_value = 5 
    ### this will be called with SOME value BUT how can I capture it?
    ### mockito-python does not seem to provide an answer to this situation either
    ### (unline its Java counterpart with ArgumentCaptor capability)
    ###
    ### Looking for something conceptually like this (using MagicMock):
    ### self.mockDep.save_out.argCapture(basestring).return_value = 11
    ###
    ### QUESTION: how could I capture value of parameters with which 
    ### 'save_out' is invoked in MagicMock?

    def setUp(self):
        self.cut = Client(self.mockDep)

    def test_create(self):
        capturedResult = self.cut.create('Z')
        self.assertEqual(capturedResult, 5, 'Unexpected sum')

        ### now argument will be of different value but we cannot assert on what it is
        capturedResult = self.cut.create('a')
        self.assertEqual(capturedResult, 5, 'Unexpected sum')

如果有人能告诉我如何完成这两个模拟场景(使用 MagicMock),我将非常感激! (有不清楚的地方请追问。)

最佳答案

可能对您有帮助的是使用 assert_called_with与匹配器。 这将使您能够更细粒度地访问调用中的参数。即:

>>> def compare(self, other):
...     if not type(self) == type(other):
...         return False
...     if self.a != other.a:
...         return False
...     if self.b != other.b:
...         return False
...     return True

>>> class Matcher(object):
        def __init__(self, compare, some_obj):
            self.compare = compare
            self.some_obj = some_obj
        def __eq__(self, other):
            return self.compare(self.some_obj, other)

>>> match_foo = Matcher(compare, Foo(1, 2))
>>> mock.assert_called_with(match_foo)

关于python - 如何在Python中进行参数匹配、捕获,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21390836/

相关文章:

java - 我想使用 spy 来模拟方法,但我需要获得一些虚拟数据作为返回

python - pip install dryscrape 失败,出现 "error: [Errno 2] No such file or directory: ' src/webkit_server'”?

java - 将字符串从 Java 程序传递到 Python 程序

java - 添加方法java

java - 如何从java中的线程传播异常?

python - 如何在 Python 中使用模拟文件对象进行单元测试?

python - 将 POST 方法从 Flask 更改为 Django

python - 启动shell的多个进程

java - 如何创建类和链接方法

c++ - 无趣的模拟函数调用 bla() && 预期 : to be called at least once bla()?