2015-04-07 52 views
1

我有一個類,我需要打補丁,其工作原理類似於此子類MagicMock在python

class Foo(object): 
    def __init__(self, query): 
     self._query = query 

    def do_stuff(self): 
     # do stuff with self._query 

我將如何建立一個嘲諷類美孚這樣

foo = MockFoo(query) 
foo.do_stuff() 

返回模擬結果,但仍考慮到傳入的數據爲query。我認爲子類MagicMock像這樣

class MockFoo(MagicMock): 
    def __init__(self, query, *args, **kwargs): 
     super(MagicMock, self).__init__(*args, **kwargs) 
     self._query 

    def do_stuff(self): 
     mock_result = self._query * 10 
     return MagicMock(return_value=mock_result) 

,但我不能完全弄清楚如何申請patch在實際的TestCase使用MockFoo,而不是MagicMock。我需要能夠寫出類似於此的測試。

with patch('x.Foo') as mock_foo: 
    # run test code 
    self.assertTrue(mock_foo.called) 
    self.assertEqual(mock_foo.wait.return_value, 20) 

我知道我可以只使用純MagicMockautospec=True或東西,覆蓋原來的返回值的每一種方法,但它會是不錯的一個模擬類,我就可以用它來代替生產類一氣呵成。關鍵之處在於,必須在構造函數中初始化(就像生產類一樣),在模擬方法中訪問成員變量self._query

+0

我不認爲這是可行的,因爲在某種程度上你需要區分真正的方法/屬性和模擬的方法/屬性。諸如「called」和「return_value」是模擬的一部分,因此將它們添加到生產類的修改實例是不可行的。我認爲最好按照你所說的嘲笑你所需要的,並且可能添加一些輔助代碼來做。 –

回答

1

關於你的基礎問題的答案是使用patchnew_callable參數:如果你需要一些參數添加到MockFoo初始化調用認爲在patch不使用的每一個參數將是passet到模擬構造

with patch('x.Foo', new_callable=MockFoo) as mock_foo: 
    # run test code 
    self.assertTrue(mock_foo.called) 
    self.assertEqual(mock_foo.wait.return_value, 20) 

MockFoo在你的情況)。

如果你需要生產類的包裝,也許你看錯了地方:模擬不是包裝。

當你嘲笑某些事情時,你並不真正想知道你的模擬如何完成這項工作,而只是你的代碼如何使用它,以及你的代碼如何對模擬對象的答案做出反應。