同时使用 junit 断言和 mockito 验证
Using both junit assertions and mockito verification
我将 Junit 与 Mockito 结合使用。我使用mockito的verify方法+junit assertion来做完整的验证。这是不可取的吗?我们应该使用一个还是另一个而不是两者?
两者并用没有错。
Mockito 的 verify
用于断言在给定的 mock 上调用了一个方法(使用预期的参数)。
JUnit 的assertXYZ
用于断言某些结果具有预期值。
两者都是有效的验证,如果两者相关,则两者都应该使用。
例如,考虑以下(当然是人为的)情况:
您有一个执行某些数学计算的界面:
public interface ValueProducer {
public int getValue(int val);
}
还有一个 class 可以将它产生的任何结果加倍:
public class Doubler {
public static int doubleThatResult (ValueProducer producer, int val) {
return 2 * producer.getValue(val);
}
}
测试它需要断言两件事:
getValue
被正确调用
- 结果翻倍
所以,例如:
public class DoublerTest {
@Test
public void testDoubleThatResult() throws Exception {
int value = 7; // Or any other value
int returnMock = 13; // Or any other value
ValueProducer producerMock = mock(ValueProducer.class);
when(producerMock.getValue(value)).thenReturn(returnMock);
int actual = Doubler.doubleThatResult(producerMock, value);
verify(producerMock);
assertEquals(26, actual);
}
}
Mureinik 的回答是绝对正确的——断言和验证是互补的,并且可以很好地协同工作——但对一个行为同时进行这两种操作可能是多余的。
目标通常是尽可能以最灵活和与实现无关的方式表达测试。从这个意义上说,状态测试(带有断言)通常是最合适的选择:只要结果状态正确,调用哪些方法并不重要。 Mockito 验证虽然可能,但可能会引入脆弱性(代码行为正确但测试被破坏)。 Mockito 本身在 verify(T)
's Javadoc and the linked article by Mockito's creator Szczepan Faber.
中对此发出警告
这种冗余当然不是最糟糕的事情:它确实测试了系统的 属性,并且在测试与敏感的、遗留的、第三方的或经常变化的依赖项的交互时可能是值得的尝试.但是,如果交互不重要,这些额外的验证可能会以脆弱性为代价。
其他时候,确认正确的行为意味着测试副作用——例如,确保 someSystem.reset()
被调用,或者通过验证提供者未被调用来测试缓存。这些是验证的完美示例,因为与外部服务的交互是关键的可测试行为。在其中一些情况下,Mockito 验证是 唯一 做出正确断言的方法。
很多测试用例都是以上的组合,所以断言和验证可以自由搭配使用;请记住,状态测试通常就足够了,而且更可取。
我将 Junit 与 Mockito 结合使用。我使用mockito的verify方法+junit assertion来做完整的验证。这是不可取的吗?我们应该使用一个还是另一个而不是两者?
两者并用没有错。
Mockito 的 verify
用于断言在给定的 mock 上调用了一个方法(使用预期的参数)。
JUnit 的assertXYZ
用于断言某些结果具有预期值。
两者都是有效的验证,如果两者相关,则两者都应该使用。
例如,考虑以下(当然是人为的)情况:
您有一个执行某些数学计算的界面:
public interface ValueProducer {
public int getValue(int val);
}
还有一个 class 可以将它产生的任何结果加倍:
public class Doubler {
public static int doubleThatResult (ValueProducer producer, int val) {
return 2 * producer.getValue(val);
}
}
测试它需要断言两件事:
getValue
被正确调用- 结果翻倍
所以,例如:
public class DoublerTest {
@Test
public void testDoubleThatResult() throws Exception {
int value = 7; // Or any other value
int returnMock = 13; // Or any other value
ValueProducer producerMock = mock(ValueProducer.class);
when(producerMock.getValue(value)).thenReturn(returnMock);
int actual = Doubler.doubleThatResult(producerMock, value);
verify(producerMock);
assertEquals(26, actual);
}
}
Mureinik 的回答是绝对正确的——断言和验证是互补的,并且可以很好地协同工作——但对一个行为同时进行这两种操作可能是多余的。
目标通常是尽可能以最灵活和与实现无关的方式表达测试。从这个意义上说,状态测试(带有断言)通常是最合适的选择:只要结果状态正确,调用哪些方法并不重要。 Mockito 验证虽然可能,但可能会引入脆弱性(代码行为正确但测试被破坏)。 Mockito 本身在 verify(T)
's Javadoc and the linked article by Mockito's creator Szczepan Faber.
这种冗余当然不是最糟糕的事情:它确实测试了系统的 属性,并且在测试与敏感的、遗留的、第三方的或经常变化的依赖项的交互时可能是值得的尝试.但是,如果交互不重要,这些额外的验证可能会以脆弱性为代价。
其他时候,确认正确的行为意味着测试副作用——例如,确保 someSystem.reset()
被调用,或者通过验证提供者未被调用来测试缓存。这些是验证的完美示例,因为与外部服务的交互是关键的可测试行为。在其中一些情况下,Mockito 验证是 唯一 做出正确断言的方法。
很多测试用例都是以上的组合,所以断言和验证可以自由搭配使用;请记住,状态测试通常就足够了,而且更可取。