2012-10-05 45 views
13

我有一個Python TestCase類,除了一個之外,所有的測試方法都需要以同樣的方式修補一個對象。另一種方法需要來自同一個對象的其他行爲。我正在使用mock,所以我做了:覆蓋Python模擬的修補程序修飾器

@mock.patch('method_to_patch', mock.Mock(return_value=1)) 
class Tests(TestCase): 

    @mock.patch('method_to_patch', mock.Mock(return_value=2)) 
    def test_override(self): 
     (....) 

但是,這不起作用。當運行test_override時,它仍會調用類裝飾器的修補行爲。

大量的調試後,我發現了TestSuite生成過程中,各地test_override@patch被一個圍繞Tests之前調用,因爲mock應用補丁的順序,類裝飾壓倒一切的方法裝飾。

此命令是否正確?我期待着相反的,我不知道如何覆蓋修補...也許與with聲明?

+0

'test_override'是否需要在'Tests'中?我可以想象有另一個'TestCase'用於'test_override'和類似的測試。如果你希望所有'method_to_patch'對'test_override'做一件事情,而不是另一件事情,那麼我也可以想象擁有另一個'TestCase'類是合理的。這也可以解決你的問題,並且使代碼更易於被其他開發者讀取(與「修補修補」相比)。 –

+0

@SimeonVisser由於我們用來構造測試的規則,將'test_override'移動到另一個類並不是一個真正的選擇。它們都是相對於同一個視圖的測試,所以我們把'em'放在一個'TestCase'中 – Gabe

回答

18

那麼,事實證明,一個良好的睡眠和冷水淋浴讓我重新思考整個問題。 我對嘲笑的概念還很陌生,所以它仍然沒有完全正確地沉沒。

事情是,沒有必要重寫補丁到嘲笑的對象。這是一個嘲弄的對象,這意味着我可以讓它做任何事情。所以我的第一次嘗試是:

@mock.patch('method_to_patch', mock.Mock(return_value=1)) 
class Tests(TestCase): 

    def test_override(self): 
     method_to_patch.return_value = 2 
     (....) 

這工作,但有副作用,改變所有後續測試的返回值。所以然後我嘗試:

@mock.patch('method_to_patch', mock.Mock(return_value=1)) 
class Tests(TestCase): 

    def test_override(self): 
     method_to_patch.return_value = 2 
     (....) 
     method_to_patch.return_value = 1 

它的工作就像一個魅力。但似乎是太多的代碼。於是我去了下來上下文管理之路,像這樣:

@mock.patch('method_to_patch', mock.Mock(return_value=1)) 
class Tests(TestCase): 

    def test_override(self): 
     with mock.patch('method_to_patch', mock.Mock(return_value=2): 
      (....) 

我覺得這好像更清晰,更簡潔。

關於patch修飾器的應用順序,它實際上是正確的順序。就像堆棧裝飾器從下到上應用一樣,應該在類裝飾器之前調用一個方法裝飾器。我想這是有道理的,我只是期待着相反的行爲。

無論如何,我希望這可以幫助像我這樣的一些可憐的新手靈魂。