mockito:如何匹配java 8中的varargs?

时间:2014-03-24 21:10:31

标签: java mockito java-8

我正在努力将一个项目从java 7迁移到8,并且在Mockito中遇到了编译错误“当”我遇到困难的情况下追踪时:

when(queryRunner.query(any(String.class), any(ResultSetHandler.class), anyVararg())).thenReturn(mockedWordResultList);

给我一​​个编译错误:

java: reference to query is ambiguous   both method
<T>query(java.lang.String,java.lang.Object,org.apache.commons.dbutils.ResultSetHandler<T>)
in org.apache.commons.dbutils.QueryRunner and method
<T>query(java.lang.String,org.apache.commons.dbutils.ResultSetHandler<T>,java.lang.Object...)
in org.apache.commons.dbutils.QueryRunner match

此错误发生在构建1.8.0-b128中,但不会发生在1.7.0_45中。我正在使用mockito 1.9.5。

在java 8中使用anyVarArg()参数匹配的正确方法是什么?

1 个答案:

答案 0 :(得分:7)

问题是类型推断已得到改进。 anyVararg()是一种通用方法,但您在嵌套方法调用中使用它。在Java 8之前,类型推断的限制在将<T> T anyVararg()作为参数放在另一个方法调用而不插入显式类型参数时强制将<Object> Object anyVararg()视为处理。

所以只有query(String, ResultSetHandler, Object...)匹配,因为第三个参数被视为Object类型。

但现在使用Java 8类型推断可以使用嵌套方法调用。由于<T> T anyVararg()类型参数<T>可以只是任何,因此它也可以是ResultSetHandler。所以query(String,Object,ResultSetHandler)现在也是匹配候选人。

(在两种情况下,我从外部调用中省略了类型参数<T>,以减少混淆)

由于我们现在有两种可能的匹配,因此这里适用方法选择的正常程序。是的,这是模棱两可的。第一个参数是相同的String,但是对于其他两个ResultSetHandlerObject更具体,但是当一个候选者接受第二个参数的更具体类型时,另一个参数为第三(和后续)。

很明显,允许方法返回类型的类型参数只是一个模糊性的来源,但像Mockito包含这些方法的API是Java编程的一个极端情况。您必须使用通用方式Matchers.<Desired>anyVararg()或通过类型转换(Desired)anyVararg()强制输入类型。