Java Mockito:使用有界通配符返回类型的存根方法

Java Mockito:使用有界通配符返回类型的存根方法,java,unit-testing,generics,mockito,bounded-wildcard,Java,Unit Testing,Generics,Mockito,Bounded Wildcard,考虑以下代码: 公共类DummyClass{ public List我假设您希望能够使用一些已知值加载someList;这里有一种方法,它使用Answer和模板化的助手方法来保证所有类型的安全: @Test public void testMockitoWithGenericsUsingAnswer() { DummyClass dummyClass = Mockito.mock(DummyClass.class); Answer<List<Integer>

考虑以下代码:

公共类DummyClass{

public List我假设您希望能够使用一些已知值加载
someList
;这里有一种方法,它使用
Answer
和模板化的助手方法来保证所有类型的安全:

@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;
}
@测试
public void TestMockito with GenericsUsingAnswer()
{
DummyClass DummyClass=Mockito.mock(DummyClass.class);
答案=设置Dummylistanswer(77,88,99);
Mockito.when(dummyClass.dummyMethod())。然后回答(answer);
...
}
私人应答设置Dummylistanswer(N…值){
final List someList=new ArrayList();
addAll(Arrays.asList(values));
答案=新答案(){
公共列表应答(invocationMock调用)抛出可丢弃的{
返回一些列表;
}   
};
返回答案;
}

您也可以为此使用非类型安全方法

@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());
}

昨天我遇到了同样的问题。来自@nondescript1和@millhouse的两个答案都帮助我找到了解决办法。我几乎使用了与@millhouse相同的代码,只是我让它更通用了一点,因为我的错误不是由
java.util.List
引起的,而是由
com.google.common.base.Optional
引起的。我的小小帮助因此,er方法允许任何类型的
T
,而不仅仅是
List

这可以很好地编译,并执行与
thenReturn(…)
方法相同的操作


有人知道Java编译器发出的错误是编译器错误还是代码确实不正确吗?

尽管Marek Radonsky提出的实用方法可行,但还有一个选项甚至不需要fikovnik建议的(看起来很奇怪的)lambda表达式:

对于类似的问题,您也可以使用以下选项:

BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();
我在这里给出一个答案,让它更具可视性,因为我认为它是使用Java8+的最优雅的解决方案

建议使用
doReturn()
(如接受的答案中所建议的)仅作为最后手段

相反,为了避免问题中描述的编译器错误,建议的Mockito
when()
方法可以与
thenAnswer()
和lambda(而不是helper方法)一起使用:


你能更新你的代码片段来显示泛型类型吗?完成了。我不得不删除pre和code标记,他们正在剥离这似乎简单明了,而且,据我所知,是正确的。我不知道为什么Mockito没有提供类似的东西……除非它提供了。在Java 8中,它可以缩短:
Mockito.when(dummyClass.dummyMethod())。然后回答(x->someList)
,因此不需要该实用程序method@fikovnik“thenAnswer”是一个多么伟大的发现啊!这对我也有一定的帮助……但是如果您希望返回的列表不是空的,会发生什么呢?您可以不使用空列表,而是执行以下操作:list someList=new ArrayList();someList.add(aNumber);虽然它没有给出任何编译时错误,但返回的列表是空的,即使我们传递的是包含条目的列表。
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));
BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();
Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)