Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 基于泛型类型与Mockito匹配参数_Java_Mockito - Fatal编程技术网

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>