使用不同的參數模擬相同的方法
1. 概述
在 Java 中模擬方法時,根據傳入的參數接收不同的響應可能很有用。在本文中,我們將根據需求的複雜性研究實現該目標的不同方法。
2. 設置
首先,讓我們創建一個要模擬的示例服務:
class ExampleService {
int getValue(int arg){
return 1;
}
}
我們通過單一方法提供了非常簡單的服務。該方法有一個int
作為參數並返回一個int
。請注意,參數和返回值沒有關係,因此默認情況下,它將始終返回 1。
3. 連續存根的局限性
讓我們看看連續存根以及我們能用它做什麼和不能做什麼。無論我們提供什麼輸入,我們都可以使用連續存根從模擬中按順序獲取不同的參數。這顯然缺乏對將特定輸入與所需輸出匹配的控制,但在許多情況下很有用。為此,我們將要存根的方法傳遞給when()
。然後,我們鏈接調用thenReturn()
按照我們想要的順序提供響應:
@Test
void givenAMethod_whenUsingConsecutiveStubbing_thenExpectResultsInOrder(){
when(exampleService.getValue(anyInt())).thenReturn(9, 18, 27);
assertEquals(9, exampleService.getValue(1));
assertEquals(18, exampleService.getValue(1));
assertEquals(27, exampleService.getValue(1));
assertEquals(27, exampleService.getValue(1));
}
從斷言中我們可以看到,儘管總是傳入 1 作為參數,但我們還是按順序收到了期望值。一旦返回所有值,所有未來的調用都將返回最終值,如我們測試中的第四個調用所示。
4. 不同參數的存根調用
我們可以擴展when()
和thenReturn()
的使用,為不同的參數返回不同的值:
@Test
void givenAMethod_whenStubbingForMultipleArguments_thenExpectDifferentResults() {
when(exampleService.getValue(10)).thenReturn(100);
when(exampleService.getValue(20)).thenReturn(200);
when(exampleService.getValue(30)).thenReturn(300);
assertEquals(100, exampleService.getValue(10));
assertEquals(200, exampleService.getValue(20));
assertEquals(300, exampleService.getValue(30));
}
when()
的參數是我們想要存根的方法,以及我們想要指定響應的值。通過將對when()
調用與thenReturn(),
我們指示模擬在收到正確的參數時返回請求的值。我們可以自由地將任意數量的這些應用到我們的模擬中以處理一系列輸入。每次提供預期的輸入值時,我們都會收到請求的返回值。
5. 使用thenAnswer()
提供最大控制的更複雜的選項是使用thenAnswer()
。這允許我們獲取參數,對它們執行我們想要的任何計算,然後返回一個在與模擬交互時輸出的值:
@Test
void givenAMethod_whenUsingThenAnswer_thenExpectDifferentResults() {
when(exampleService.getValue(anyInt())).thenAnswer(invocation -> {
int argument = (int) invocation.getArguments()[0];
int result;
switch (argument) {
case 25:
result = 125;
break;
case 50:
result = 150;
break;
case 75:
result = 175;
break;
default:
result = 0;
}
return result;
});
assertEquals(125, exampleService.getValue(25));
assertEquals(150, exampleService.getValue(50));
assertEquals(175, exampleService.getValue(75));
}
上面,我們在提供的調用對像上使用getArguments()
獲取了參數。我們在這裡假設了一個int
參數,但我們可以滿足幾種不同的類型。我們還可以檢查是否至少有一個參數並且強制轉換為int
是否成功。為了演示這些功能,我們使用switch
語句根據輸入返回不同的值。在底部,我們可以從斷言中看到我們的模擬服務返回switch
語句的結果。
這個選項允許我們通過一次調用when()
來處理無限數量的輸入。犧牲的是測試的可讀性和可維護性。
六,結論
在本教程中,我們了解了配置模擬方法以返回不同值的三種方法。我們研究了連續存根,發現它對於按順序返回任何輸入的已知值很有用,但除此之外就非常有限。對每個潛在輸入使用when()
與thenReturn()
相結合提供了一個具有改進控制的簡單解決方案。或者,我們可以使用thenAnswer()
來最大程度地控制給定輸入和預期輸出之間的關係。根據測試的要求,這三種方法都有用。
與往常一樣,示例的完整代碼可在 GitHub 上獲取。