Java 莫基托“;核实;检查当前状态,但不重置模拟调用
我在JUnit测试中使用Mockito。该测试是一个集成测试,测试整个场景,因此其中有许多断言和Java 莫基托“;核实;检查当前状态,但不重置模拟调用,java,junit,mockito,Java,Junit,Mockito,我在JUnit测试中使用Mockito。该测试是一个集成测试,测试整个场景,因此其中有许多断言和verify(mock)s 我的问题是,我正在编写一些生产代码,执行一些断言,然后验证mock是否有效,直到有一个相同的mock调用。请参见简化代码: interface I { void m1(); void m2(); } // some decorator class T implements I { public T(I decorated) { /*
verify(mock)
s
我的问题是,我正在编写一些生产代码,执行一些断言,然后验证mock是否有效,直到有一个相同的mock调用。请参见简化代码:
interface I {
void m1();
void m2();
}
// some decorator
class T implements I {
public T(I decorated) {
/*...*/
}
/* ... */
}
public void testInvalid() {
I m = mock(I.class);
T t = new T(m);
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m).m1();
t.m2();
assertEquals("m2", t.getLastMethod());
verify(m).m2();
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m).m1();
// TooManyActualInvocations t.m1(): Wanted 1 time, but was 2 times ...
}
public void testValid() {
I m = mock(I.class);
T t = new T(m);
t.m1();
assertEquals("m1", t.getLastMethod());
t.m2();
assertEquals("m2", t.getLastMethod());
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m, times(2)).m1();
verify(m).m2();
}
一个想法是在最后验证mock,但是假设有一个小的愚蠢的实现错误,它导致调用方法m1两次,m2一次,但不像我在testInvalid
中预期的那样,但最终测试会通过。我希望我的考试早点失败。我如何做到这一点
多谢各位
感谢@Woozy Coder:
我没有提到,reset
也将是一个选项,但是由于必须在verify和下一个相等存根调用之间调用它,因此我认为很难编写“好的”和正确的测试。应该有两种不同的模拟样式:
earlyReset(m).after(
new Runnable() {
t.someMethodInvokingTwoStubs();
verify(m).someMethod1();
verify(m).someMethod2();
}
);
Mockito是为了避免脆弱性而编写的,因此验证可以使最不特定的断言成为可能,从而允许实现在不改变测试的情况下发展。如果多次调用这些方法对您的测试系统没有关系,那么您不应该让Mockito检查它 备选方案:
- 使用
或至少
确保调用完全发生,而不必担心调用该方法的额外次数至少一次
- 如果该调用被存根化为具有返回值,则可以根据您所存根的数据的状态断言推断系统工作
- 如果您确实需要在单个测试方法中更改存根或验证行为,那么您的mock可能会超出Mockito擅长的范围。使用单个方法的答案,或者编写一份手册,正确模拟相互关联的方法
clearInvocations()
(在Mockito 2.1中提供)
使用
reset()
有一个缺点,即您也会松开存根,clearInvocations()
只会清除调用。尝试一下,不要在一个测试方法中测试多个方法。一个测试应该有一个它测试的东西,最好是一个可能失败的东西。测试多种方法会使测试更加复杂。将测试分为多种测试方法将解决这个问题。@WoozyCoder谢谢,编辑了我的post@FlorianSchaetz这是一个集成测试。它测试一个有限状态机,分别是TDD,因为我想写一些生产代码来帮助我设计它。它使用的所有组件都经过单元测试,但是状态机使用了很多反射,我的测试是一个带有内部测试类和注释的场景。它从IDLState开始,IDLState应该调用onIdle
,然后我们选择一张票据,支付它,它应该返回IDLState并再次调用onIdle
。这是一个安静而复杂的测试,但它是状态机实现以及功能文档的基础。一开始我希望能打电话给onIdle,最后在买票之后<代码>至少(2)结尾对我来说太模糊了。我认为Mockito不适合这样的集成测试,但是我非常喜欢Mockito,因为它很容易使用。这救了我一天!