Java 如何在Mockito上验证多个条件中的一个是否满足?是否可以验证是否调用了一个或另一个方法?

Java 如何在Mockito上验证多个条件中的一个是否满足?是否可以验证是否调用了一个或另一个方法?,java,android,junit,mockito,Java,Android,Junit,Mockito,在我的单元测试中,我想检查是否调用了一个或另一个方法。多亏了Mockito,我可以很容易地验证一些方法被调用了多少次,但是verify没有像“OR”这样的验证模式。有解决办法吗 在我的例子中,我想检查onSharedPreferences.Editor是否被调用为.apply()或.commit(),因为这两种可能性满足了我的要求并保存了数据。不幸的是,如果我调用verify(mEditor).apply(),但在示例中,由于需要即时保存,有人将实现更改为.commit(),测试将失败,但不应该

在我的单元测试中,我想检查是否调用了一个或另一个方法。多亏了Mockito,我可以很容易地验证一些方法被调用了多少次,但是
verify
没有像“OR”这样的验证模式。有解决办法吗


在我的例子中,我想检查on
SharedPreferences.Editor
是否被调用为
.apply()
.commit()
,因为这两种可能性满足了我的要求并保存了数据。不幸的是,如果我调用
verify(mEditor).apply()
,但在示例中,由于需要即时保存,有人将实现更改为
.commit()
,测试将失败,但不应该失败,因为我只想从这个角度测试数据是否保存。这是单元测试,应该独立于这样的更改,只检查内部测试的范围。

我不知道有什么好方法可以做到这一点,老实说,我认为真正的答案是:做而不是做那件事。是的,另一个答案显示了实现您要求的方法,但是:

您知道生产代码应该做什么。意思:与其编写一段允许“thisthat”的验证代码,不如编写两个独立的测试,一个用于“this”,另一个用于“that”

换句话说:你可以控制测试的内容。因此,编写一个测试,该测试将导致
apply()
,另一个测试将导致
commit()
。然后
验证()


单元测试应该是直接的。当某个测试失败时,您可以快速查看单元测试,并且已经知道在生产代码中查找哪里可以找到根本原因。任何增加测试复杂性的事情都可能使测试更加困难。最好有两个测试遵循一个明确的“when-then-verify”路径,而不是有一个(或多个)测试“when-then-verify”或“verify-that”。

您要求的解决方法是捕获底层(或只是
AssertionError
):

或者,如果
apply
commit
都调用一些(内部)
save
方法,您也可以尝试验证这一点(假设它是公开的——基于模拟的测试可能与信息隐藏不一致)。或者,如果你能控制你正在测试的代码,你可以按照这些思路重构它


但是,更好的建议是,完全避免这种需要,如中所述。

好的,你有很好的建议,但是如果我编写两个单独的测试-一个应该导致
apply()
和一个
commit()
,其中一个总是会失败,对吗?或者你的意思是只关注我应该知道它是如何在生产代码上实现的?问题是这两种方法都达到了我(和我的单元测试)的预期,都保存了数据。一种是异步方式,另一种是立即执行,这两种方式在这里都是可以接受的。也许我错了,但当我从测试的角度看问题和思考问题时,我想知道满足测试名称要求的最低要求是什么。@user3054470当然,这是一条模糊的线。但正如所说的:单独的测试应该测试一条特定的路径。这条路应该对测试的读者清晰可见。您可以看到,至少在谈到单元测试时,如果希望调用apply()或commit(),则会产生很大的不同。那么为什么不进行测试,每个测试都有一个特定的目标呢?功能/集成测试可能会有所不同。
try {
  verify(mEditor).apply();
} catch (MockitoAssertionError mae) {
  // apply was not called. Let's verify commit instead.
  verify(mEditor).commit();
}