Mockito - 你不能在验证或存根之外使用参数匹配器 - 已经尝试了很多东西但仍然没有解决方案

Mockito - You cannot use argument matchers outside of verification or stubbing - have tried many things but still no solution

我有如下一段代码:

PowerMockito.mockStatic(DateUtils.class);      
//And this is the line which does the exception - notice it's a static function  
PowerMockito.when(DateUtils.isEqualByDateTime (any(Date.class),any(Date.class)).thenReturn(false);

class 开头为:
@RunWith(PowerMockRunner.class) @PrepareForTest({CM9DateUtils.class,DateUtils.class})

我得到org.Mockito.exceptions.InvalidUseOfMatchersException......你不能在验证或存根之外使用参数匹配器.....(错误出现两次失败跟踪 - 但都指向同一行)

在我的代码的其他地方,when 的用法已完成并且工作正常。另外,在调试我的代码时,我发现 any(Date.class) returns null。

我尝试了以下解决方案,我看到其他人发现这些解决方案很有用,但对我来说不起作用:

  1. 正在添加 @After public void checkMockito() { Mockito.validateMockitoUsage(); }

    @RunWith(MockitoJUnitRunner.class)

    @RunWith(PowerMockRunner.class)

  2. 改为 PowerMockito.when(new Boolean(DateUtils.isEqualByDateTime(any(Date.class), any(Date.class)))).thenReturn(false);

  3. 使用anyObject()(不编译)

  4. 正在使用 notNull(Date.class)(Date)notNull()

  5. 替换 when(........).thenReturn(false);


    Boolean falseBool=new Boolean(false);

    when(.......).thenReturn(falseBool);

PowerMockito Getting Started Page 中所述,您需要使用 PowerMock 运行器和 @PrepareForTest 注释

@RunWith(PowerMockRunner.class)
@PrepareForTest(DateUtils.class)

确保您使用的是 JUnit 4 附带的 @RunWith 注释,org.junit.runner.RunWith。因为它总是接受 value 属性,所以如果您使用正确的 RunWith 类型,您会收到该错误,这对我来说很奇怪。

any(Date.class) 对 return null 是正确的:Mockito 没有使用魔术 "matches any Date" 实例,而是使用 a hidden stack of matchers 来跟踪哪些匹配器表达式对应匹配的参数,returns null 对象(整数为 0,布尔值为 false,等等)。

所以最后,对我有用的是将执行异常的行导出到其他一些静态函数。我称之为 compareDates.

我的实现:

在被测试的class中(例如-MyClass
static boolean compareDates(Date date1, Date date2) { return DateUtils.isEqualByDateTime (date1, date2); }

并在测试中 class:
PowerMockito.mockStatic(MyClass.class); PowerMockito.when(MyClass.compareDates(any(Date.class), any(Date.class))).thenReturn(false);

不幸的是,我不能说我完全理解为什么这个解决方案有效而以前的没有。
也许这与 DateUtils class 不是我的代码有关,我无法访问它的源代码,只能访问生成的 .class 文件,但我真的不确定。


编辑

上述解决方案只是一种解决方法,并未解决在代码中覆盖 DateUtils isEqualByDateTime 调用的需要。
实际上 解决了真正的问题是导入具有实际实现的 DateUtils class 而不是只是扩展它的那个,这是我之前导入的.

这样做之后我可以使用原来的线路

PowerMockito.mockStatic(DateUtils.class);      

PowerMockito.when(DateUtils.isEqualByDateTime (any(Date.class),any(Date.class)).thenReturn(false);

无一例外。

我在 Kotlin 测试 Class

中遇到了与 TextUtils 类似的问题
PowerMockito.`when`(TextUtils.isEmpty(Mockito.anyString())).thenReturn(true)

通过在我的测试之上添加以下代码解决了这个问题Class

 @PrepareForTest(TextUtils::class)

并在 PowerMockito 之前调用了 mockStatic。`when`

PowerMockito.mockStatic(TextUtils::class.java)