在我的单元测试中,我想检查是否调用了一个或另一个方法。借助 Mockito,我可以轻松验证某些方法被调用了多少次,但verify
没有像"OR"这样的验证模式。有什么解决方法吗?
就我而言,我想检查SharedPreferences.Editor
是否被称为.apply()
或.commit()
,因为其中两种可能性满足我并保存数据。不幸的是,如果我打电话给verify(mEditor).apply()
但由于即时保存的要求,有人会将实现更改为.commit()
,测试将失败,但不应该,因为我只想从这个角度测试数据是否保存。它是单元测试,应该独立于此类更改,并且只检查内部测试的范围。
您要求的工作是捕获底层的 MockitoAssertionError(或只是AssertionError
):
try {
verify(mEditor).apply();
} catch (MockitoAssertionError mae) {
// apply was not called. Let's verify commit instead.
verify(mEditor).commit();
}
或者,如果apply
和commit
都调用某种(内部)save
方法,您也可以尝试验证(假设它是公开的 - 基于模拟的测试可能与信息隐藏不一致)。或者,如果您可以控制要测试的代码,则可以按照这些行重构它。
不过,更好的建议是完全避免这样做,正如@GhostCat在回答中所论证的那样。
我不知道有什么好方法可以做到这一点,老实说,我认为真正的答案是:不要那样做。是的,另一个答案显示了实现您要求的方法,但是:
您知道您的生产代码应该做什么。意思是:与其写一段允许"这个或那个"的验证码,不如写两个独立的测试,一个用于"这个">,一个用于"那个"。
换句话说:您可以控制测试的内容。所以写一个应该导致apply()
的测试,和一个应该导致commit()
的测试。然后verify()
每个测试都应该看到的一个案例!
单元测试应该是直截了当的。当某些内容失败时,您可以快速查看单元测试,并且您已经知道在生产代码中查找何处以发现根本原因。任何增加测试复杂性的事情都可能使测试变得更加困难。最好有两个测试遵循明确的"何时验证"路径,而不是有一个(或多个)测试"何时验证此或验证"。