2015-03-02 40 views
2

我知道我問這個問題意味着我可能完全不懂嘲笑。我知道爲什麼使用模擬(隔離),我知道如何使用模擬(每個FW和它的方式) - 但我不明白 - 如果嘲笑的目的是爲了返回預期值隔離我的單元測試,爲什麼應該我嘲笑一個對象,而不僅僅是自己創造價值?模擬對象和設置一個值有什麼區別

爲什麼這樣的:

$searchEngine = Mockery::mock('elasticSearch'); 
    $searchEngine->shouldReceive('setupDataConnection')->once()->andReturn("data connected"); 

    $insertData = new DataInserter; 
    $this->assertEquals("data connected",$insertData->insertData($searchEngine)); 

而不是這個:

$knownResult = "data connected"; 
    $insertData = new DataInserter; 
    $this->assertEquals($insertData->insertData($searchEngine) ,$knownResult); 

編輯 很抱歉的錯誤,但意外地不包括insertData在第二個例子。

回答

2

通過使用模擬,您可以訪問來自直接像C風格struct(僅執行數據存儲)行爲的對象的附加信息,然後幾乎沒有什麼區別(關於斷言有關您的模擬調用通常是相當有用的,因爲您可以確保您的值例如設置爲3次而不是7(可能有一些可能導致潛在問題的中間值)。

模擬對於測試對象之間的交互很有用。

現在,如果你的類做了更復雜的事情(比如像訪問數據庫這樣的資源,或者從文件中讀取/寫入數據),那麼mocks因爲它們幾乎允許你抽象出未經測試的類的內部行爲(例如,讓我們假設你的類的第一個版本只是將值存儲在內存中,下一個版本將它們存儲在一個特定的地方數據庫,這樣你可以首先爲數據庫訪問節省資源,其次能夠有效地證明被測試的類正常工作,而不是證明數據訪問類正常工作。如果你有一個失敗的測試,那麼你可以立即磨練這個問題,而不是試圖弄清楚問題出在你的數據提供者還是數據訪問者。 )

因爲測試可以並行運行,某些資源可能會導致錯誤的失敗。交互這是非常難以測試沒有嘲笑 有幾個例子是:進行對話的一個數據庫訪問層

  1. 碼(確保查詢是正確的,close()方法被稱爲連接上,和適當的SQL )
  2. 文件/套接字IO(再次確保數據是一致的)
  3. 系統調用(例如,調用php執行)
  4. 任何依賴線程/時序的問題(並不是PHP中的一個問題)
  5. GUI代碼(再次,在PHP中幾乎聽不到)但如果我將語言轉換爲讓它說java明顯更容易調用: when(myDialogBoxMock).showOptionInputDialog()。然後返回(「mockInput」) 然後試圖用子類或臨時實現/子類僞造它。
  6. 調用只能用特定值調用的特定方法。 verify(myMock.setValue(7),times(2)); verifyNoOtherInteractions(myMock);

這很大一部分也是速度問題,如果你正在讀取一個文件脫離磁盤可以說300/400倍在一個巨大的代碼庫,那麼你肯定會注意到通過使用模擬的速度增加。

如果您在PHP中爲Java提供了類似EMMA/jacoco的工具,您將能夠獲得有效的代碼覆蓋率報告,以顯示您的測試不覆蓋代碼的位置。在任何非平凡的應用程序中,您都會發現自己試圖弄清楚如何讓測試對象進入特定的狀態以測試特定的行爲,而使用DI進行模擬真的是您執行這些任務的工具。

+0

謝謝你的回覆,你能給我一些真實生活的例子,我可能需要在不使用模擬的情況下測試對象之間進行交互嗎? – cmvr 2015-03-02 10:39:11

+0

@cmvr我編輯了這篇文章,提供了6個立即想到的例子。 – 2015-03-02 11:07:15

+0

我很抱歉,但我不知道我明白。如果嘲笑我可以使用(例如)實際上並沒有連接到DB的類(或者甚至可能不存在) - 這是如何幫助我驗證我的查詢是正確的?另外,如果嘲笑的地方是隔離,爲什麼我想在無關的單元測試中測試我的查詢?感謝您花時間來解釋和詳細解答。 – cmvr 2015-03-02 12:51:38

0

在第一個示例中,您爲DataInserter提供了僞合作者($ searchEngine)。在assert語句中,您調用insertData,它將執行DataInserter的邏輯,該邏輯將與僞造的$ searchEngine進行互動。通過提供僞造,您可以驗證DataInserter的邏輯是否可以單獨正確工作。

在第二個示例中,您未測試DataInserter邏輯。您只是檢查常量字符串$ knownResult是否等於「數據連接」,即您正在測試php的字符串相等。據我可以從代碼片段中看到,您構建了一個新的DataInserter對象,但是您甚至在測試中沒有執行其代碼。

+0

對不起,但請看我的編輯。 – cmvr 2015-03-02 09:46:17

+0

你可以發佈整個第二次測試嗎?例如,$ searchEngine變量是如何初始化的? – prgmtc 2015-03-02 09:52:49

相關問題