Java Mockito mocking when()用于两个不同类型的泛型方法

Java Mockito mocking when()用于两个不同类型的泛型方法,java,generics,mockito,Java,Generics,Mockito,我有两个类generic的泛型对象: genericOne; 泛型2; 我不得不嘲笑: when(someObject.someMethod(Matchers.<Generic<TypeA, TypeB>>any())) .thenReturn(responseOne()); when(someObject.someMethod(Matchers.<Generic<TypeB, TypeC>>any()))

我有两个类
generic
的泛型对象:

genericOne;
泛型2;
我不得不嘲笑:

when(someObject.someMethod(Matchers.<Generic<TypeA, TypeB>>any()))
                .thenReturn(responseOne());

when(someObject.someMethod(Matchers.<Generic<TypeB, TypeC>>any()))
                .thenReturn(responseTwo());
when(someObject.someMethod(Matchers.any()))
。然后返回(responseOne());
当(someObject.someMethod(Matchers.any()))
。然后返回(responsewo());
问题是mockito不会看到这两个方法调用之间的区别,因为类型擦除-它都被认为是
Generic
class


有什么方法可以区分这两个方法调用吗?

Mockito不知道在
any()
调用之前指定了哪些泛型,无论如何,这都不重要

模拟行为记录中预期的参数必须依赖于:

  • 值(以
    equals()表示)
  • 如果
    equals()
    不充分,那么就俘虏而言
  • 或者
    any()
    ,如果模拟调用中的参数值无关紧要或者在测试夹具中未知
它们永远不必依赖于上指定的泛型

要获得一个好的示例,请查看
Mockito.anyCollectionOf(Class clazz)
Mockito.anyMapOf(Class keyClazz,Class valueClazz)

这些方法知道传递的类,但无论如何,它们的规范声明:

此方法不进行任何类型检查,只是为了避免 强制转换代码。但是,这可能会更改(类型检查可能会更改) 添加)在未来的主要版本中

通常,您要检查的是,mock方法是使用预期参数而不是任何参数调用的:因此
any()
将永远无法实现它。
因此,尝试只检查泛型类型但接受任何值作为参数似乎是一种反模式模拟。


在您的情况下,如果
equals()
不便于在
when()
录制中进行匹配,请将Mockito captor与
verify()
一起使用,并在执行mock后进行检查。

我认为不可能区分这两种类型,因为使用了泛型类型。但还有其他选项

您可以将此调用耦合到特定顺序,以便即使mockito无法区分它们,它也会返回预期值。这是通过链接
thenReturn
方法完成的。第一个调用返回
responseOne()
,第二个调用返回
ResponseTo()

when(someObject.someMethod(Matchers.any()))
.thenReturn(responseOne())
。然后返回(responsewo());
但这并不是最优的,因为如果您的实现发生变化,这个测试就会中断

您可以实现此对象的自定义。以便更好地控制此实例的行为。例如

class SomeObjectFake {

    private final SomeResponse response;

    public SomeObject(SomeResponse response) {
        this.response = response;
    }

    public SomeResponse someMethod(Generic<TypeA, TypeB> arg) {
        // Decide what to return
        return response;
    }
}
类SomeObjectFake{
私人最终反应;
公共SomeObject(SomeResponse响应){
这个。反应=反应;
}
公共SomeResponse someMethod(泛型参数){
//决定归还什么
返回响应;
}
}

你可以使用
然后回答
而不是
然后返回
,并实现任何你想要的东西-如此简单!欢迎你。除了一个不可能很好的具体解决方法之外,我更愿意提供一个更广泛的想法,说明如何使用预期参数进行模拟,因为编写功能代码的人是决定使用什么的最佳人选hich策略根据其用例进行选择。
when(someObject.someMethod(Matchers.<Generic<TypeA, TypeB>>any()))
    .thenReturn(responseOne())
    .thenReturn(responseTwo());
class SomeObjectFake {

    private final SomeResponse response;

    public SomeObject(SomeResponse response) {
        this.response = response;
    }

    public SomeResponse someMethod(Generic<TypeA, TypeB> arg) {
        // Decide what to return
        return response;
    }
}