【问题标题】:Is it possible to do strict mocks with Mockito?是否可以使用 Mockito 进行严格的模拟?
【发布时间】:2011-12-21 15:25:26
【问题描述】:

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

据我所知,如果我没有定义任何期望,Mockito 只会返回 null,这稍后会在其他地方导致 NullPointerException。

有可能做到吗?如果是,怎么做?

【问题讨论】:

    标签: java unit-testing testing mocking mockito


    【解决方案1】:

    你想让它做什么?

    您可以将其设置为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();
        }
    }
    

    【讨论】:

    • 哇,看起来不错。可能也是 Mockito 2.0 中的默认退货策略……
    • 除非可以让它抛出异常而不是返回值,否则似乎没有任何帮助..
    • @devouredelysium 任何帮助?这显然是错误的,即使它没有做你想要的。就像我说的,应该很容易修改。
    • 但是它告诉你在哪里调用了返回空值的方法,而不是在哪里使用了空对象。这不是你所追求的吗?在某些情况下,返回 null 可能不会对您的测试造成任何问题,因此您无需为其提供返回值。抛出异常会迫使您解决不影响测试的问题...
    • @avh 你可以使用doReturn("X").when(mock).toString()
    【解决方案2】:

    根据 org.mockito.Mockito.RETURNS_DEFAULTS 的源代码,它从全局设置中选择“如果没有期望怎么办”。 此外“如果没有全局配置,那么它使用 {@link ReturnsEmptyValues}(返回零、空集合、空值等)” 我还不能进行那个配置。

    【讨论】:

      【解决方案3】:

      您可以使用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)
          ...
      

      【讨论】:

        【解决方案4】:

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

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

        此值已添加到版本 2.3.0 的 Mockito 中

        来自文档:

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

        • 提高生产力:在测试代码时测试提前失败 使用不同的参数调用存根方法(参见 潜在的StubbingProblem)。
        • 无需不必要的清洁测试 存根:当存在未使用的存根时,测试失败(参见 UnnecessaryStubbingException)。
        • 更干净、更干燥的测试(“不要重复 你自己”):如果你使用 Mockito.verifyNoMoreInteractions(Object...) 你 不再需要显式验证存根调用。他们是 自动为您验证。

        【讨论】:

          【解决方案5】:

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

          @RunWith(MockitoJUnitRunner.StrictStubs.class)
          

          (我本来会评论关于 MockitoRule 的帖子,但还没有那个能力)

          【讨论】:

            【解决方案6】:

            波纹管方法可以验证没有调用意外的方法:

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

            【讨论】:

              猜你喜欢
              • 2021-09-07
              • 1970-01-01
              • 1970-01-01
              • 2012-05-14
              • 1970-01-01
              • 2011-03-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多