【问题标题】:Throw a RuntimeException when invoking an unstubbed method调用未存根的方法时抛出 RuntimeException
【发布时间】:2013-03-27 21:54:15
【问题描述】:

我正在使用 Mockito。我想在调用未存根的方法时抛出RuntimeException

有什么办法吗?

【问题讨论】:

  • 你为什么要这样做?
  • 在这种情况下,您所说的“非模拟方法”到底是什么意思?使用mock(...)/@Mock时,类中的所有方法都会被模拟。
  • 因为我经常忘记模拟一些方法。异常可以帮助找到这些方法。
  • 但是如果我没有处理模拟对象的方法,那么这个方法返回null(如果它必须返回对象)
  • 我认为他的意思是所有没有被存根的方法。

标签: java mockito


【解决方案1】:

你模拟整个类,结果是所有方法都返回 null。

然后您可以使用doReturn(...) 来更改该行为。同样,您可以使用doThrow(...) 使(我记得只有void)方法抛出异常。

这能回答你的问题吗?

【讨论】:

  • 我认为他想确保所有方法都被模拟,例如,如果一个方法没有被模拟,Mockito 会抛出异常
  • 是的!但我想确保所有将被调用的方法都被模拟。
  • 模拟类中的所有方法都是模拟的——根据定义。
  • 太棒了!我希望如果我没有处理方法(例如 'when(mockedObj.getName()).thanReturn("ebala")' ),那么方法会在调用时抛出 RuntimeException。
  • 感谢'stubbing'这个词)
【解决方案2】:

您可以为模拟设置默认答案。所有未存根的方法都将使用此默认答案。

public void testUnstubbedException() {
    // Create a mock with all methods throwing a RuntimeException by default
    SomeClass someClass = mock( SomeClass .class, new RuntimeExceptionAnswer() );

    doReturn(1).when(someClass).getId(); // Must use doReturn

    int id = someClass.getId(); // Will return 1

    someClass.unstubbedMethod(); // Will throw RuntimeException
}

public static class RuntimeExceptionAnswer implements Answer<Object> {

    public Object answer( InvocationOnMock invocation ) throws Throwable {
        throw new RuntimeException ( invocation.getMethod().getName() + " is not stubbed" );
    }

}

请注意,您不能when 与此功能一起使用,因为该方法在when (How does mockito when() invocation work?) 之前调用,并且在模拟进入存根之前它会抛出RuntimeException模式。

因此,您必须使用 doReturn 才能使其工作。

【讨论】:

  • 谢谢!但是当我插入 'when(someClass.unmpokedMethod()).thanReturn("huerga")' 时,它会继续抛出异常
  • 您必须使用doReturn 而不是when。我用这个解决方案编辑了我的答案。
  • 这太糟糕了,这需要doReturn 和一些额外的工作,而不是人们对这样一个共同愿望的预期
【解决方案3】:

最好的方法是使用verifyNoMoreInteractionsignoreStubs 静态方法。在测试的“行为”部分之后调用它们;如果调用了任何未存根的方法但未经过验证,您将失败。

verifyNoMoreInteractions(ignoreStubs(myMock));

https://static.javadoc.io/org.mockito/mockito-core/2.8.47/org/mockito/Mockito.html#ignore_stubs_verification 对此进行了描述,尽管我认为那里的代码示例当前包含打印错误。

【讨论】:

  • 如果您的测试在此之前由于调用未模拟的方法引起的空取消引用而模糊地崩溃,这将无济于事。
【解决方案4】:

完善汤姆的回答https://stackoverflow.com/a/15835255/1484823

Mockito 现在提供内置支持,默认答案会引发异常,并且可以使用 @Mock 注释指定

    @Mock(answer = Answers.RETURNS_SMART_NULLS)
    private BackingAppDeploymentService backingAppDeploymentService;

    private BackingAppDeploymentService  backingAppDeploymentService =
      Mockito.mock(BackingAppDeploymentService.class, new ReturnsSmartNulls());

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#RETURNS_SMART_NULLS

如果您的代码使用由未存根调用返回的对象,您会收到 NullPointerException。 Answer 的这个实现返回 SmartNull 而不是 null。 SmartNull 提供比 NPE 更好的异常消息,因为它指出了调用未存根方法的行。您只需单击堆栈跟踪。

ReturnsSmartNull 首先尝试返回普通值(零、空集合、空字符串等),然后尝试返回 SmartNull。如果返回类型是 final 则返回纯 null。

ReturnsSmartNulls 可能是 Mockito 4.0.0 中的默认返回值策略

【讨论】:

  • 这不是被问到的。如果从未使用过返回的“smart null”,则不会出现运行时异常。因此,这并不能回答关于“忘记模拟方法时出现异常”的问题
猜你喜欢
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 2011-04-13
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多