Mockito:有界通配符返回types的存根方法

考虑这个代码:

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()的行为。 任何关于如何使用有界通配符返回types的方法的指针?

您也可以使用非types安全方法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的谷歌组织所讨论的那样 。

虽然这比thenAnswer简单,但再次注意它不是types安全的。 如果您担心types安全,那么Millhouse的答案是正确的。

额外细节

要清楚,这里是观察到的编译器错误,

然后返回方法返回(List <capture#1-of?extends Number>)types为OngoingStubbing <List <capture#1-of? 扩展Number >>不适用于参数(List <capture#2-of?extends Number>)

我相信编译器在when调用期间分配了第一个通配符types,然后无法确认thenReturn调用中的第二个通配符types是否相同。

它看起来像thenAnswer不会遇到这个问题,因为它接受通配符types, thenReturn采取非通配符types,必须捕获。 从Mockito的正在进行的工作中 ,

 OngoingStubbing<T> thenAnswer(Answer<?> answer); OngoingStubbing<T> thenReturn(T value); 

我假设你想能够加载someList与一些已知的价值; 下面是一个使用Answer<T>和模板帮助器方法来保持所有types安全的方法:

 @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 。 因此,我的小帮手方法允许任何types的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编译器发出的错误是编译器错误,还是代码真的不正确?

尽pipeMarek Radonsky提出的效用方法有效,但还有一个选项甚至不需要(imHO奇怪的)lambdaexpression式fikovnik:

正如这个类似问题的答案所示,您还可以使用以下内容:

 BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();