[英]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.