mrm*_*sra 117 java generics unit-testing mockito bounded-wildcard
考虑以下代码:
public class DummyClass {
public List<? extends Number> dummyMethod() {
return new ArrayList<Integer>();
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨正在尝试存根行为的行dummyMethod()
.关于如何使用有界通配符返回类型的存根方法的任何指针?
Joh*_*thy 173
您也可以使用非类型安全方法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());
}
Run Code Online (Sandbox Code Playgroud)
正如Mockito的谷歌小组所讨论的那样.
虽然这比简单thenAnswer
,但请注意它不是类型安全的.如果你担心类型安全,那么millhouse的答案是正确的.
要清楚,这是观察到的编译器错误,
然后返回方法返回(List <capture#1-of?extends Number>)类型为OngoingStubbing <List <capture#1-of?extends Number >>不适用于参数(List <capture#2-of?extends Number>)
我相信编译器在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
采用非通配符类型,必须捕获它.来自Mockito的OngoingStubbing,
OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenReturn(T value);
Run Code Online (Sandbox Code Playgroud)
mil*_*use 32
我假设您希望能够加载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;
}
Run Code Online (Sandbox Code Playgroud)
小智 14
我昨天打了同样的话.@ nondescript1和@millhouse的答案都帮助我找到了解决方法.我几乎使用与@millhouse相同的代码,除了我使它稍微更通用,因为我的错误不是由a引起的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;
}
Run Code Online (Sandbox Code Playgroud)
使用这个辅助方法,您可以编写:
Mockito.when(dummyClass.dummyMethod()).thenAnswer(createAnswer(someList));
Run Code Online (Sandbox Code Playgroud)
这个编译很好,并且与thenReturn(...)
方法做同样的事情.
有人知道Java编译器发出的错误是编译器错误还是代码真的不正确?
我正在将fikovnik的评论变成这里的答案,以提高其可见性,因为我认为这是使用 Java 8+ 的最优雅的解决方案。
该的Mockito文档建议使用doReturn()
(如在接受答案的建议)只作为最后的手段。
相反,为了规避问题中描述的编译器错误,推荐的 Mockitowhen()
方法可以与thenAnswer()
lambda一起使用(而不是辅助方法):
Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
75397 次 |
最近记录: |