Java 基于泛型类型与Mockito匹配参数
我正在寻找一种方法,使模拟函数根据其参数的泛型类型返回不同的值。例如,如果参数是Java 基于泛型类型与Mockito匹配参数,java,mockito,Java,Mockito,我正在寻找一种方法,使模拟函数根据其参数的泛型类型返回不同的值。例如,如果参数是Generic的任何实例,则执行某些操作,如果参数是Generic的任何实例,则执行其他操作 我想我可以使用以下代码来完成: @Mock private Getter getter; @Rule public final Mocks mocks = new Mocks(this); @Test public void testSearch(){ doReturn("Foo<Boolean>")
Generic
的任何实例,则执行某些操作,如果参数是Generic
的任何实例,则执行其他操作
我想我可以使用以下代码来完成:
@Mock
private Getter getter;
@Rule
public final Mocks mocks = new Mocks(this);
@Test
public void testSearch(){
doReturn("Foo<Boolean>").when(getter).getValue(Matchers.<Foo<Boolean>>any());
doReturn("Foo<String>").when(getter).getValue(Matchers.<Foo<String>>any());
System.out.println(getter.getValue(new Foo<Boolean>()));
System.out.println(getter.getValue(new Foo<String>()));
}
public static class Foo<T> {
}
public class Getter {
<T> String getValue(BumapinRefOdsHandlerTest.Foo<T> foo) {
return "not-used";
}
}
@Mock
私人消气剂;
@统治
公共最终模拟模拟=新模拟(本);
@试验
公共void testSearch(){
doReturn(“Foo”).when(getter).getValue(Matchers.any());
doReturn(“Foo”).when(getter).getValue(Matchers.any());
System.out.println(getter.getValue(new Foo());
System.out.println(getter.getValue(new Foo());
}
公共静态类Foo{
}
公共类Getter{
字符串getValue(BumapinRefOdsHandlerTest.Foo Foo){
返回“未使用”;
}
}
但是代码打印出来了
Foo<String>
Foo<String>
Foo
福
根据泛型类型匹配参数的正确方法是什么?您不能这样做。在运行期间,由于擦除,类型
Foo
和Foo
将减少为相同的类型Foo
。下面的断言将成立
assert new Foo<Boolean>().getClass().equals(new Foo<String>().getClass())
assert new Foo().getClass().equals(new Foo().getClass())
对于编译期间使用的类型参数,无法测试基本泛型类,除非该类是一个子类,并且可以从类定义中推断出来,或者在方法签名中完全指定了该类。乙二醇
//使用反射可以恢复FooBoolean使用的类型参数Boolean
类FooBoolean扩展了Foo{…}
//在方法上使用反射可以恢复foo的类型参数
使某物无效(Foo Foo){…}
泛型在运行时不直接可用。对你来说呢
doReturn("Foo<Boolean>").when(getter).getValue(Matchers.<Foo<Boolean>>any());
doReturn("Foo<String>").when(getter).getValue(Matchers.<Foo<String>>any());
输出将是
Foo<Boolean>
Foo<Boolean>
Foo
福
在记录模拟对象之前,在Getter类中填充getValue方法以满足您的需求。如果您不能这样做,为什么mockito应该支持它。因此,请替换[return“not used”]。从技术上讲,您不能在运行时执行此操作,Mockito没有机会知道是传入了Foo还是Foo。检查“类型擦除”:“泛型仅在编译时可用”这不是真的。可以恢复方法签名中使用的泛型类型参数以及类定义中使用的值。@flakes,附加问题,我们可以在运行时使用字节码工程工具(如BCEL)检索这些泛型类型信息吗?您可以使用内置java反射库,请参阅@flakes,不应该使用这样一个笼统的语句,但我的意思是在这个示例的上下文中,不可能在运行时获得泛型类型。相应地更新了答案。TIL。我认为java中的泛型与C++中的模板类似。即,编译器为每个泛型实例生成单独的类定义。在阅读了有关擦除的内容后,这是完全有道理的。
doReturn("Foo<String>").when(getter).getValue(Matchers.<Foo<String>>any());
doReturn("Foo<Boolean>").when(getter).getValue(Matchers.<Foo<Boolean>>any());
Foo<Boolean>
Foo<Boolean>