Java泛型-方法不适用于Mockito生成的存根
我有一个Java泛型-方法不适用于Mockito生成的存根,java,generics,mockito,Java,Generics,Mockito,我有一个ThingsProvider接口,我正试图用Mockito(简化版)进行测试,定义如下: interface ThingsProvider { Iterable<? extends Thing> getThings() } 。。。但这在非测试代码中显然是不好的 我的问题: 为什么这是一个错误?很明显,我返回的对象扩展了东西,这正是接口所期望的 有没有更好的办法解决这个问题?也许我的界面定义不同?到目前为止,除了测试之外,我还没有遇到这个问题 关于#2-我之所以不简单
ThingsProvider
接口,我正试图用Mockito(简化版)进行测试,定义如下:
interface ThingsProvider {
Iterable<? extends Thing> getThings()
}
。。。但这在非测试代码中显然是不好的
我的问题:
东西
,这正是接口所期望的对于那些不太熟悉Mockito的人,下面是#1的更纯Java版本:
public static void main(String...args) {
List<Integer> ints = Arrays.asList(1,2,3);
blah(ints);
Foo<Number> foo1 = new Foo<Number>();
foo1.bar(ints); // This works
Foo<? extends Number> foo2 = new Foo<Number>();
foo2.bar(ints); // NO COMPILEY!
}
private static void blah(List<? extends Number> numberList) {
// something
}
public static class Foo<T> {
public Object bar(List<? extends T> tList) {
return null;
}
}
publicstaticvoidmain(字符串…参数){
List ints=Arrays.asList(1,2,3);
废话;
Foo foo1=新的Foo();
foo1.bar(ints);//这很有效
Foo重构为两个步骤
OngoingStubbing<Iterable<? extends Thing>> stub = when(thingsProvider.getThings());
stub.thenReturn(things);
正如您所观察到的,返回类型中的通配符对于子类实现非常方便
不过,它对方法的调用者没有太大影响;如果愿意,您可以将其更改为Iterable
;在javadoc上更简单,代价是子类实现者。子类可以在必要时执行强制转换,例如List=>Iterable
,这要归功于擦除
出现问题的原因是通配符捕获;基本上,在计算上下文表达式之前,每个表达式都首先进行通配符捕获
foo( arg )
arg
总是先捕获通配符,然后再执行方法适用性/重载/推断。在您的情况下,您可以尝试更通用的类型IterablecanMockito.Hm,这是一种有趣的替代解决方法!由于类型安全问题,不一定比问题中概述的当前解决方法更好…@Chri你的意思是在编辑之前吗?是的,键入安全性不太好。我不喜欢这样删除答案的解决方案。是的,我在上面的评论中引用了原始答案。我将在稍后仔细查看修订版。谢谢更新!
OngoingStubbing<Iterable<? extends Thing>> stub = when(thingsProvider.getThings());
stub.thenReturn(things);
Mockito.<Iterable<? extends Thing>>when(thingsProvider.getThings())
foo( arg )
Mockito.<Iterable<? extends Thing>>when(...
OngoingStubbing<Iterable<? extends Thing>> stub = when(...
static <T> OngoingStubbing<T> whenX( Supplier<T> sup )
{
return Mockito.when( sup.get() );
}
whenX(thingsProvider::getThings).thenReturn(things);
// T = Iterable<? extends Thing>
List<Thing> things = ...;
ThingsProvider thingsProvider = ()->things;