使用Mockito基于泛型类型匹配参数



我正在寻找一种方法,使mock函数根据其参数的泛型类型返回不同的值。例如,如果参数是Generic<Foo>的任何实例,则执行某些操作,如果参数为Generic<Bar>的任何实例则执行其他操作。

我想我可以使用以下代码来简化它:

@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";
}
}

但是代码打印

Foo<String>
Foo<String>

根据泛型类型匹配参数的正确方法是什么?

你不能这么做。在运行期间,由于擦除,类型Foo<Boolean>Foo<String>将减少为相同的类型Foo。例如,以下断言将保持

assert new Foo<Boolean>().getClass().equals(new Foo<String>().getClass())

对于编译过程中使用的类型参数,没有办法测试基本泛型类,除非该类是子类,并且可以从类定义中推断,或者在方法签名中完全指定。例如

// Using reflection can recover that FooBoolean used type parameter Boolean
class FooBoolean extends Foo<Boolean> { ... }
// Using reflection on the Method can recover the type parameter of foo
void something(Foo<Boolean> foo) { ... }

泛型在运行时不直接可用。在你的情况下

doReturn("Foo<Boolean>").when(getter).getValue(Matchers.<Foo<Boolean>>any());
doReturn("Foo<String>").when(getter).getValue(Matchers.<Foo<String>>any());

将使用Foo类型的任何参数来终止方法调用。所以最后一个存根获胜,在您的情况下是doReturn("Foo<String>")

如果您将订单反转为

doReturn("Foo<String>").when(getter).getValue(Matchers.<Foo<String>>any());
doReturn("Foo<Boolean>").when(getter).getValue(Matchers.<Foo<Boolean>>any());

输出将是

Foo<Boolean>
Foo<Boolean>

最新更新