基于具有Mockito的泛型类型的匹配参数

时间:2018-11-09 13:20:04

标签: java mockito

我正在寻找一种使模拟函数根据其参数的通用类型返回不同值的方法。例如,如果参数是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>

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

2 个答案:

答案 0 :(得分:3)

您不能这样做。在运行时,由于擦除,类型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) { ... }

答案 1 :(得分:1)

泛型在运行时不直接可用。而就您而言

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>