2014-01-27 18 views
1

我想了解如何在模擬方法參數匹配和參數捕獲時模擬python外部依賴項。如何做參數匹配,在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-蟒能夠適應下面的嘲笑場景好的文檔或示例:

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),我將非常感激! (請問是否有什麼不清楚。)

+1

你是什麼意思的「參數匹配」?它與*嘲諷*有什麼關係? – Bakuriu

回答

1

東西可能會幫助你使用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) 
+0

如果你不想自己編寫匹配器,你可以嘗試一個我最近發佈的庫,它已經有很多了:https://github.com/Xion/callee – Xion