2014-01-27 2 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 с помощью Matcher. Это позволит вам получить более тонкий доступ к тексту аргументов ваших вызовов. то есть:

>>> 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

Смежные вопросы