使用 Mockito Spy 模擬同一測試類別中的方法
1. 概述
模擬在單元測試中是一個非常有用的功能,特別是在隔離我們想要在方法中測試的單一行為時。在本教程中,我們將了解如何使用 Mockito Spy 在同一測試類別中模擬方法。
2. 理解問題
單元測試是第一級測試,也是我們針對錯誤的第一道防禦。然而,有時一個方法過於複雜,需要多次調用,尤其是在遺留程式碼中,我們並不總是有重構的可能性。為了簡化單元測試,我們將使用一個簡單的範例來展示 Mockito Spy 的強大功能。
對於我們的範例,讓我們引入一個類別CatTantrum
:
public class CatTantrum {
public enum CatAction {
BITE,
MEOW,
VOMIT_ON_CARPET,
EAT_DOGS_FOOD,
KNOCK_THING_OFF_TABLE
}
public enum HumanReaction {
SCREAM,
CRY,
CLEAN,
PET_ON_HEAD,
BITE_BACK,
}
public HumanReaction whatIsHumanReaction(CatAction action){
return switch (action) {
case MEOW -> HumanReaction.PET_ON_HEAD;
case VOMIT_ON_CARPET -> HumanReaction.CLEAN;
case EAT_DOGS_FOOD -> HumanReaction.SCREAM;
case KNOCK_THING_OFF_TABLE -> HumanReaction.CRY;
case BITE -> biteCatBack();
};
}
public HumanReaction biteCatBack() {
// Some logic
return HumanReaction.BITE_BACK;
}
}
方法whatIsHumanReaction()
包含一些邏輯和對方法biteCatBack()
的呼叫。我們將重點放在whatIsHumanReaction()
方法的單元測試。
3.使用Mockito Spy的解決方案
讓我們使用 Mockito Spy 編寫單元測試:
@Test
public void givenMockMethodHumanReactions_whenCatActionBite_thenHumanReactionsBiteBack(){
// Given
CatTantrum catTantrum = new CatTantrum();
CatTantrum catTantrum1 = Mockito.spy(catTantrum);
Mockito.doReturn(HumanReaction.BITE_BACK).when(catTantrum1).biteCatBack();
// When
HumanReaction humanReaction1 = catTantrum1.whatIsHumanReaction(CatAction.BITE);
// Then
assertEquals(humanReaction1, HumanReaction.BITE_BACK);
}
第一步是使用Mockito.spy(catTantrum).
這一行允許我們模擬whatIsHumanReaction()
所呼叫的biteCatBack()
方法的回傳值。
值得注意的是,當我們呼叫要測試的方法時,我們需要在間諜物件catTantrum1
上呼叫它,而不是在原始物件catTantrum.
Mockito 間諜允許我們直接使用類別中的一些方法並存根其他方法。如果我們使用模擬,我們將需要存根所有方法呼叫。另一方面,如果我們使用物件的真實實例,我們將無法模擬該類別中的任何方法。
在上面的範例中,Mockito Spy 允許我們在同一個物件catTantrum1
上呼叫真正的方法whatIsHumanReaction()
,並呼叫方法的存根biteCatBack()
。
4. 結論
在本文中,我們學習如何使用 Mockito Spy 來解決在同一測試類別中模擬方法的問題。
我們應該記住,通常最好寫出更簡單、單一用途的方法。但如果這是不可能的,使用 Mockito Spy 可以幫助繞過這種複雜性。
範例的完整原始碼可在 GitHub 上取得。