有可能用Mockito做严格的模拟吗?



我希望使用严格的模拟,至少在第一次针对旧代码开发一些测试时是这样,所以如果我没有明确定义期望,那么在模拟上调用的任何方法都将抛出异常。

从我所看到的来看,如果我没有定义任何期望,Mockito将只返回null,这将在稍后在其他地方引起NullPointerException。

这可能吗?如果是,怎么做?

你想让它做什么?

您可以将其设置为RETURN_SMART_NULLS,这样可以避免NPE并包含一些有用的信息。

您可以用自定义实现来替换它,例如,从它的answer方法抛出一个异常:

@Test
public void test() {
    Object mock = Mockito.mock(Object.class, new NullPointerExceptionAnswer());
    String s = mock.toString(); // Breaks here, as intended.
    assertEquals("", s);
}
class NullPointerExceptionAnswer<T> implements Answer<T> {
    @Override
    public T answer(InvocationOnMock invocation) throws Throwable {
        throw new NullPointerException();
    }
}

您可以使用verifyNoMoreInteractions。如果被测试的类捕获异常,它是有用的。

@Test
public void testVerifyNoMoreInteractions() throws Exception {
    final MyInterface mock = Mockito.mock(MyInterface.class);
    new MyObject().doSomething(mock);
    verifyNoMoreInteractions(mock); // throws exception
}
private static class MyObject {
    public void doSomething(final MyInterface myInterface) {
        try {
            myInterface.doSomethingElse();
        } catch (Exception e) {
            // ignored
        }
    }
}
private static interface MyInterface {
    void doSomethingElse();
}
结果:

org.mockito.exceptions.verification.NoInteractionsWanted: 
No interactions wanted here:
-> at hu.palacsint.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
But found this interaction:
-> at hu.palacsint.CatchTest$MyObject.doSomething(CatchTest.java:24)
Actually, above is the only interaction with this mock.
    at hu.palacsint.stackoverflow.y2013.q8003278.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    ...

@Rule添加到您的测试类中作为公共字段:

@RunWith(JUnitParamsRunner.class)
public class MyClassTests {
    @Rule
    public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
    @Test
    ....
}

此值在2.3.0版本中添加到Mockito

来自文档:

确保干净的测试,减少测试代码重复,改进debuggability。提供最佳的灵活性和生产力。强烈推荐。作为Mockito v3的默认计划。添加以下行为:

  • 提高生产力:在测试代码时,测试较早失败调用带有不同参数的存根方法(参见PotentialStubbingProblem)。
  • Cleaner测试而无需进行不必要的测试存根:当存在未使用的存根时,测试会失败(参见UnnecessaryStubbingException)。
  • 更干净,更多DRY测试("不要重复你自己"):如果你使用Mockito.verifyNoMoreInteractions(Object…不再需要显式地验证存根调用。他们是

根据org.mockito. mockitto的源代码。它从全局设置中选择"如果没有期望要做什么"。此外,"如果没有全局配置,那么它使用{@link ReturnsEmptyValues}(返回零,空集合,null等)"

除了MockitoRule方法之外,如果您不需要使用特定的测试运行器(并且您正在使用Mockito 2.5.1或更高版本),您还可以考虑使用MockitoJUnitRunner.StrictStubs运行器,即

@RunWith(MockitoJUnitRunner.StrictStubs.class)

(我本想评论关于MockitoRule的帖子,但还没有这个功能)

Bellow方法可以验证没有意外的方法调用:

org.mockito.Mockito#only
org.mockito.Mockito#verifyNoMoreInteractions

相关内容

  • 没有找到相关文章

最新更新