[英]Mockito: Stubbing Methods That Return Type With Bounded Wild-Cards
考慮這個代碼:
public class DummyClass {
public List<? extends Number> dummyMethod() {
return new ArrayList<Integer>();
}
}
public class DummyClassTest {
public void testMockitoWithGenerics() {
DummyClass dummyClass = Mockito.mock(DummyClass.class);
List<? extends Number> someList = new ArrayList<Integer>();
Mockito.when(dummyClass.dummyMethod()).thenReturn(someList); //Compiler complains about this
}
}
編譯器抱怨試圖存根dummyMethod()
行為的dummyMethod()
。 關於如何處理返回帶有有界通配符的類型的方法的任何指針?
為此,您還可以使用非類型安全的方法doReturn ,
@Test
public void testMockitoWithGenerics()
{
DummyClass dummyClass = Mockito.mock(DummyClass.class);
List<? extends Number> someList = new ArrayList<Integer>();
Mockito.doReturn(someList).when(dummyClass).dummyMethod();
Assert.assertEquals(someList, dummyClass.dummyMethod());
}
正如在 Mockito 的 google group 上討論的那樣。
雖然這比thenAnswer
簡單,但再次注意它不是類型安全的。 如果您擔心類型安全,millhouse 的答案是正確的。
需要明確的是,這是觀察到的編譯器錯誤,
The method thenReturn(List<capture#1-of ? extends Number>) in the type OngoingStubbing<List<capture#1-of ? extends Number>> is not applicable for the arguments (List<capture#2-of ? extends Number>)
我相信編譯器在when
調用期間分配了第一個通配符類型,然后無法確認thenReturn
調用中的第二個通配符類型是否相同。
看起來thenAnswer
沒有遇到這個問題,因為它接受通配符類型,而thenReturn
接受必須捕獲的非通配符類型。 從 Mockito 的OngoingStubbing ,
OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenReturn(T value);
我假設您希望能夠使用一些已知值加載someList
; 這是一種使用Answer<T>
和模板化輔助方法來保持所有類型安全的方法:
@Test
public void testMockitoWithGenericsUsingAnswer()
{
DummyClass dummyClass = Mockito.mock(DummyClass.class);
Answer<List<Integer>> answer = setupDummyListAnswer(77, 88, 99);
Mockito.when(dummyClass.dummyMethod()).thenAnswer(answer);
...
}
private <N extends Number> Answer<List<N>> setupDummyListAnswer(N... values) {
final List<N> someList = new ArrayList<N>();
someList.addAll(Arrays.asList(values));
Answer<List<N>> answer = new Answer<List<N>>() {
public List<N> answer(InvocationOnMock invocation) throws Throwable {
return someList;
}
};
return answer;
}
我昨天碰到了同樣的事情。 @nondescript1 和 @millhouse 的兩個答案都幫助我找到了解決方法。 我幾乎使用了與@millhouse 相同的代碼,只是我使它稍微更通用,因為我的錯誤不是由java.util.List
引起的,而是由com.google.common.base.Optional
引起的。 因此,我的小助手方法允許使用任何類型T
而不僅僅是List<T>
:
public static <T> Answer<T> createAnswer(final T value) {
Answer<T> dummy = new Answer<T>() {
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
return value;
}
};
return dummy;
}
使用此輔助方法,您可以編寫:
Mockito.when(dummyClass.dummyMethod()).thenAnswer(createAnswer(someList));
這編譯得很好,並且與thenReturn(...)
方法做同樣的事情。
有人知道Java編譯器發出的錯誤是編譯器錯誤還是代碼真的不正確?
我正在將fikovnik的評論變成這里的答案,以提高其可見性,因為我認為這是使用 Java 8+ 的最優雅的解決方案。
Mockito 文檔建議僅將doReturn()
(如已接受的答案中所建議)用作最后的手段。
相反,為了規避問題中描述的編譯器錯誤,推薦的 Mockito when()
方法可以與thenAnswer()
和 lambda(而不是輔助方法)一起使用:
Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)
盡管 Marek Radonsky 提出的實用方法有效,但還有另一個選項甚至不需要(恕我直言,看起來很奇怪)lambda 表達式 fikovnik 建議:
至於這個答案對一個類似問題節目,你也可以使用以下命令:
BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.