栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何验证未引发异常

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何验证未引发异常

tl; dr

  • JDK8之后:使用 AssertJ 或自定义lambda来声明 异常 行为。

  • JDK8之前的版本:我将推荐旧的好

    try
    -
    catch
    块。( 不要忘记
    fail()
    在该
    catch
    块之前添加一个断言

无论是Junit 4还是JUnit 5。

长话

可以自己编写自己 做的代码

try
-
catch
阻止或使用JUnit工具(
@Test(expected = ...)
@RuleExpectedException
JUnit规则功能)。

但是这些方法并不那么优雅,并且在 可读性方面没有 与其他工具很好地融合在一起。而且,JUnit工具确实存在一些陷阱。

  1. try
    -
    catch
    块,你必须写周围的测试行为块,写在catch块的断言,这可能是罚款,但很多人觉得这种风格中断测试的阅读流程。另外,您需要
    Assert.fail
    在代码
    try
    块的末尾写一个。否则,测试可能会遗漏断言的某一方面; PMDfindbugsSonar 会发现此类问题。

  2. @Test(expected = ...)
    功能很有趣,因为您可以编写更少的代码,然后编写此测试的代码据说不那么容易出错。 但是 在某些领域缺少这种方法。

    • 如果测试需要检查有关异常的其他内容,例如原因或消息(好的异常消息非常重要,那么具有精确的异常类型可能还不够)。
    • 同样,由于方法中的期望值很高,这取决于测试代码的编写方式,然后测试代码的错误部分会引发异常,从而导致测试结果呈假阳性,并且我不确定 PMDfindbugsSonar 将提供有关此类代码的提示。
          @Test(expected = WantedException.class)

      public void call2_should_throw_a_WantedException__not_call1() {
      // init tested
      tested.call1(); // may throw a WantedException

      // call to be actually testedtested.call2(); // the call that is supposed to raise an exception

      }

  3. ExpectedException
    规则也是试图解决以前的警告,但是由于使用期望样式,使用它感觉有点尴尬, EasyMock 用户非常了解这种样式。对于某些人来说可能很方便,但是如果您遵循 行为驱动开发 (BDD)或“ 安排行为声明” (AAA)原则,则该
    ExpectedException
    规则将不适合那些写作风格。除此之外,它可能会遇到与
    @Test
    方式相同的问题,具体取决于您放置期望的位置。

        @Rule ExpectedException thrown = ExpectedException.none()    @Test    public void call2_should_throw_a_WantedException__not_call1() {        // expectations        thrown.expect(WantedException.class);        thrown.expectMessage("boom");        // init tested        tested.call1(); // may throw a WantedException        // call to be actually tested        tested.call2(); // the call that is supposed to raise an exception    }

即使预期的异常位于测试语句之前,如果测试遵循BDD或AAA,它也会破坏您的阅读流程。

另外,请参见的作者关于JUnit的注释问题

ExpectedException
。JUnit
4.13-beta-2
甚至不赞成使用此机制:

拉取请求#1519:弃用ExpectedException

Assert.assertThrows方法提供了一种验证异常的更好方法。另外,与其他规则(如TestWatcher)一起使用时,ExpectedException的使用容易出错,因为在这种情况下,规则的顺序很重要。

因此,以上所有这些选项都有很多警告,并且显然无法避免编码错误。

  1. 创建这个答案后,我意识到一个项目看起来很有希望,那就是 catch-exception

正如该项目的描述所言,它使编码人员可以流畅地编写一行代码以捕获该异常,并为后者的断言提供此异常。而且,您可以使用任何断言库,例如Hamcrest或AssertJ。

来自主页的一个快速示例:

        // given: an empty list    List myList = new ArrayList();    // when: we try to get the first element of the list    when(myList).get(1);    // then: we expect an IndexOutOfBoundsException    then(caughtException()) .isInstanceOf(IndexOutOfBoundsException.class) .hasMessage("Index: 1, Size: 0")  .hasNoCause();

如您所见,代码确实非常简单,您可以在特定行上捕获异常,该

then
API是将使用AssertJ API的别名(类似于using
assertThat(ex).hasNoCause()...
)。 在某些时候,该项目依赖于FEST-声明AssertJ的祖先编辑:
似乎该项目正在酝酿对Java 8 Lambdas的支持。

当前,该库有两个缺点:

* 在撰写本文时,值得注意的是,该库基于Mockito 1.x,因为它创建了幕后测试对象的模拟。由于Mockito仍未更新, **因此该库无法使用最终类或最终方法** 。即使它基于当前版本的Mockito 2,这也需要声明一个全局模拟制作器(`inline-mock-maker`),这可能不是您想要的,因为该模拟制作器与常规模拟制作器有不同的缺点。* 它需要另一个测试依赖项。

一旦库支持lambda,这些问题将不再适用。但是,该功能将由AssertJ工具集复制。

如果您不想使用catch-exception工具,请考虑所有因素,我将建议使用

try
-
catch
块的旧方法,至少可以使用JDK7。对于JDK
8用户,您可能更喜欢使用AssertJ,因为它提供的不仅仅是断言异常。

  1. 使用JDK8,lambda进入了测试环境,事实证明它们是断言异常行为的一种有趣方式。AssertJ已更新,提供了一个很好的流利API来声明异常行为。

以及使用AssertJ进行的样本测试:

        @Test    public void test_exception_approach_1() {        ...        assertThatExceptionOfType(IOException.class)     .isThrownBy(() -> someBadIOOperation())     .withMessage("boom!");     }    @Test    public void test_exception_approach_2() {        ...        assertThatThrownBy(() -> someBadIOOperation())     .isInstanceOf(Exception.class)     .hasMessageContaining("boom");    }    @Test    public void test_exception_approach_3() {        ...        // when        Throwable thrown = catchThrowable(() -> someBadIOOperation());        // then        assertThat(thrown).isInstanceOf(Exception.class)    .hasMessageContaining("boom");    }
  1. 通过对JUnit 5的近乎完全的重写,断言已得到了一些改进,作为断言正确地声明异常的开箱即用的方式,它们可能证明很有趣。但是实际上断言API仍然有点差,外面没有东西
    assertThrows
        @Test    @DisplayName("throws EmptyStackException when peeked")    void throwsExceptionWhenPeeked() {        Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());        Assertions.assertEquals("...", t.getMessage());    }

如您所见,

assertEquals
仍然在返回
void
,因此不允许像AssertJ这样的链式断言。

另外,如果您还记得与

Matcher
或发生冲突的名称
Assert
,请准备与发生相同的冲突
Assertions

我想得出一个结论:今天(2017-03-03)不论测试框架(JUnit )是什么, AssertJ 的易用性,可发现的API,快速的开发速度以及
事实上的 测试依赖性是使用JDK8的最佳解决方案。还是不可以),即使以前的JDK 感到笨拙,也应该改用

try
-
catch
块。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/570047.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号