当前位置: 首页 > 知识库问答 >
问题:

异常后验证

有宏邈
2023-03-14

我正在测试一个具有预期异常的方法。我还需要验证在抛出异常后是否调用了一些清理代码(在模拟对象上),但看起来该验证被忽略了。这是代码。我正在使用 Junit 预期异常规则来验证预期的异常。

@Rule
public ExpectedException expectedEx = ExpectedException.none();

@Test
public void testExpectedException()
{
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   expectedEx.expect(MyException.class);
   expectedEx.expectMessage("My exception message.");
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

验证似乎完全被忽略了。无论我在verify中使用什么方法,我的测试都通过了,这不是我想要的。

你知道为什么会发生这种情况吗?

共有3个答案

邢心水
2023-03-14

带有捕捉异常的更优雅的解决方案

@Test
public void testExpectedException()
{
    MockedObject mockObj = mock(MockedObject.class);
    MySubject subject = new MySubject(mockObj);

    when(subject).someMethodThrowingException();

    then(caughtException())
            .isInstanceOf(MyException.class)
            .hasMessage("My exception message.");

    verify(mockObj).someCleanup(eq(...));
}
晏经武
2023-03-14

一旦在UT中抛出异常,下面的所有代码都将被忽略。

@Test(expected = Exception.class)
public void testExpectedException() {
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   subject.doSomething(); // If this line results in an exception then all the code below this will be ignored.
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

为了解决这个问题并验证所有拨打的电话,我们可以使用“尝试”。

@Test(expected = Exception.class)
    public void testExpectedException() {
          MockedObject mockObj = mock(MockedObj.class);
          MySubject subject = new MySubject(mockedObj);
          try {
               subject.someMethodThrowingException(); 
          } finally {
             verify(mockObj).
             someCleanup(eq(...));
          }
} 
拓拔迪
2023-03-14

ExpectedException通过JUnit@Rule将整个测试方法包装在try-catch块中。当您的代码抛出一个异常时,它会向上到达堆栈中最近的try/catch,它恰好位于ExpectedException实例中(该实例检查它是否是您期望的异常)。

在Java中,如果方法中发生未捕获的异常,控件将永远不会返回到该方法中稍后的语句。同样的规则在这里适用:异常发生后,控件永远不会返回到测试中的语句。

从技术上讲,您可以将验证放在finally块中,但这往往是一个坏习惯。编辑:您的被测系统可能会抛出一个意外的异常,或者根本没有异常,这将为您提供一个有用的失败消息和跟踪;但是,如果该失败导致您的验证或断言在< code>finally块中失败,那么Java将显示该错误,而不是关于意外异常或意外成功的消息。这可能会使调试变得困难,尤其是因为您的错误将来自错误根源后面的代码行,错误地暗示它上面的代码成功了。

如果您真的需要在异常后逐个方法验证状态,那么您可以随时返回到这个习惯用法:

@Test
public void testExpectedException()
{
  MockedObject mockObj = mock(MockedObj.class);
  MySubject subject = new MySubject(mockedObj);
  try {
    subject.someMethodThrowingException();
    fail("Expected MyException.");
  } catch (MyException expected) {
    assertEquals("My exception message.", expected.getMessage());
  }
  verify(mockObj).someCleanup(eq(...));
}

更新:使用Java8的lambda表达式,您可以将功能接口调用封装在try块中,非常简洁,非常有用。我想对这种语法的支持会进入许多标准测试库。

assertThrows(MyException.class,
    () -> systemUnderTest.throwingMethod());
 类似资料:
  • 下面是我的代码: 这里有个例外: 对象“users”中字段“salary”上的字段错误:拒绝值[null];代码[NotNull.Users.Salary,NotNull.Salary,NotNull.java.lang.Integer,NotNull];参数[org.springframework.context.support.defaultmessageSourceResolvable:代码

  • 我正在测试带注释的javax验证。它们在应用程序中工作良好,方法参数上有注释。但是当我试图通过手动构建验证工厂来测试它们时 我得到以下错误。 javax。验证。ValidationException:HV000183:无法初始化“javax”。艾尔。“表达工厂”。检查类路径上是否有EL依赖项,或者改用ParameterMessageInterpolator 收到这个错误后,我在gradle文件中添

  • 问题内容: 我正在测试具有预期异常的方法。我还需要在引发异常后验证是否在某个模拟对象上调用了一些清除代码,但看起来该验证已被忽略。这是代码。我正在使用Junit 验证预期的异常。 似乎完全被忽略了。无论我采用什么方法,我的测试都通过了,这不是我想要的。 知道为什么会这样吗? 问题答案: 通过将整个测试方法通过JUnit @Rule 包装在try- catch块中来工作。当您的代码引发异常时,它将堆

  • 在dynamodb表上运行batchGetItem函数时获取ValidationException。我在密钥列表下同时提供哈希密钥和范围密钥。以下是请求和响应。 请求: 答复:

  • 向addUser控制器提交表单时发生异常 获取窗体的控制器 为什么会出现此异常,输入无效电子邮件而不是验证必须执行。

  • 从Weblogic 11c切换到Weblogic 12c后,我得到了这个异常: 我发现了有关这些主题的其他问题,但所有解决方案都是关于错误的库(Vaadin 7-Bean验证)。我认为我的Hibernate验证器与bean验证器库匹配。这就是我在WEB-INF/lib中的内容: 它会是由其他一些依赖引起的吗? EDIT我目前在我的weblogic应用程序中有这个。xml,一切正常: