sco*_*ott 15 java testing unit-testing mockito
在我的理解中,代码测试是测试结果是否正确,如计算器,我需要编写一个测试用例来验证1 + 1的结果是否为2.
但是我已经阅读了很多关于验证方法调用次数的测试用例.我很困惑.最好的例子就是我在Spring in Action中看到的:
public class BraveKnight implements Knight {
private Quest quest;
public BraveKnight(Quest quest) {
this.quest = quest;
}
public void embarkOnQuest() {
quest.embark();
}
}
public class BraveKnightTest {
@Test
public void knightShouldEmbarkOnQuest() {
Quest mockQuest = mock(Quest.class);
BraveKnight knight = new BraveKnight(mockQuest);
knight.embarkOnQuest();
verify(mockQuest, times(1)).embark();
}
}
Run Code Online (Sandbox Code Playgroud)
我真的不知道为什么他们需要验证embark()
函数被调用一次.难道你不认为embark()
在调用后肯定会被调用embarkOnQuest()
吗?或者会发生一些错误,我会在日志中看到错误消息,显示错误行号,可以帮助我快速找到错误的代码.
那么如上所述验证的重点是什么?
需要很简单:验证是否进行了正确的调用次数.在某些情况下,方法调用不应该发生,而其他情况下,它们应该发生多于或少于默认值.
考虑以下修改版本embarkOnQuest
:
public void embarkOnQuest() {
quest.embark();
quest.embarkAgain();
}
Run Code Online (Sandbox Code Playgroud)
并假设您正在测试以下错误案例quest.embark()
:
@Test
public void knightShouldEmbarkOnQuest() {
Quest mockQuest = mock(Quest.class);
Mockito.doThrow(RuntimeException.class).when(mockQuest).embark();
...
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您要确保quest.embarkAgain
未调用(或调用0次):
verify(mockQuest, times(0)).embarkAgain(); //or verifyZeroInteractions
Run Code Online (Sandbox Code Playgroud)
当然这是另一个简单的例子.还可以添加许多其他示例:
好问题.你提出了一个很好的观点,即当你可以检查结果时,模拟可能会过于迂回.但是,有一些情况会导致更强大的测试.
例如,如果某个方法需要调用外部API,则只需测试结果就会出现一些问题:
解决您的子问题:
难道你不认为在调用embarkOnQuest()之后会调用embark()吗?
测试也有助于你重构而不用担心破坏事物.这是显而易见的,是的.这会在6个月内显而易见吗?
请考虑以下代码:
public void saveFooIfFlagTrue(Foo foo, boolean flag) {
if (flag) {
fooRepository.save(foo);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不检查fooRepository.save()
调用的次数,那么您如何知道此方法是否正在执行您想要的操作?
这适用于其他void方法.如果没有返回方法,因此没有响应验证,则检查调用哪些其他方法是验证方法行为正确的好方法.