在我使用Mockito的单元测试中,我想验证是否没有抛出NullPointerException.
public void testNPENotthrown{
    Calling calling= Mock(Calling.class);
    testClass.setInner(calling);
    testClass.setThrow(true);

    testClass.testMethod();

    verify(calling,never()).method();
}

我的测试设置了testClass,设置了Calling对象和属性,以便该方法将抛出NullPointerException.

我验证Calling.method()从不被调用.

public void testMethod(){
    if(throw) {
        throw new NullPointerException();
    }

    calling.method();
}

我想要一个失败的测试,因为它抛出一个NullPointerException,然后我想写一些代码来解决这个问题.

我注意到的是,测试总是通过,因为异常从来没有被抛出测试方法.

解决方法

TL;博士

> pre-JDK8:我会推荐旧的好的try-catch块.
> post-JDK8:使用AssertJ或custom lambdas来表示异常行为.

漫长的故事

可以自己写一个自己尝试catch块或使用JUnit工具(@Test(expected = …)或@Rule ExpectedException JUnit规则功能).

但是这些方式并不那么优雅,并不能很好地与其他工具混合良好的可读性.

> try-catch块你必须围绕被测试的行为写入块,并在断块中写入断言,可能很好,但是很多查找taht这种风格会中断测试的读取流程.此外,您需要在try块的末尾写一个Assert.fail,否则测试可能会错过该断言的一边; PMD,findbugs或Sonar将会发现这样的问题.
> @Test(expected = …)功能很有趣,因为您可以编写更少的代码,然后编写此测试据说不太容易出现编码错误.但这种做法缺乏一些方面.

>如果测试需要检查异常的其他事情,如原因或消息(良好的异常消息非常重要,具有精确的异常类型可能不够).
>另外,由于期望在方法中放置,取决于测试代码的编写方式,所以测试代码的错误部分可以抛出异常,导致错误的正测试,我不知道PMD,findbugs或Sonar将会提供这样的代码的提示.

@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 tested
    tested.call2(); // the call that is supposed to raise an exception
}

> 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,则会破坏您的阅读流程.

另请参阅这个comment问题在JUnit上的ExpectedException的作者.

所以这些上面的选项都有它们所有的注意事项,显然不能免除编码器的错误.

>在创建这个看起来很有前途的答案后,我发现了一个项目,这是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();

正如你可以看到代码真的很简单,你可以捕获特定行上的异常,然后API是一个别名,它将使用AssertJ API(类似于使用assertthat(ex).hasNoCause()…)).在某些时候,项目依靠FEST-Assert AssertJ的祖先.编辑:似乎该项目正在酝酿Java 8 Lambdas支持.

目前这个图书馆有两个缺点:

>在撰写本文时,值得注意的是,这个库基于Mockito 1.x,因为它在场景后面创建了被测对象的模拟.由于Mockito尚未更新,因此该库无法使用最终类或最终方法.即使它是基于当前版本的mockito 2,这将需要声明一个全球模拟制造商(内联制造商),这可能不是你想要的,因为这个模拟器具有不同的缺点,即常规模拟器.
>它需要另一个测试依赖.

一旦图书馆支持lambdas,这些问题就不会适用,但AssertJ工具集将会复制这些功能.

考虑到如果你不想使用catch-exception工具,我会推荐try-catch块的旧的好方法,至少到JDK7.对于JDK 8用户,您可能更喜欢使用AssertJ,因为它可能不仅仅是断言异常.
>使用JDK8,羊羔进入测试场景,它们被证明是一种有趣的方式来证明异常行为. 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");
}

>随着JUnit 5的接近完全重写,断言已经是improved,他们可能会被证明是一个开箱即用的方式来证明有效的例外.但是真正的断言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)AssertJ的易用性,可发现的API,快速的开发速度和事实上的测试依赖性是JDK8的最佳解决方案,无论测试框架如何(JUnit或不是)因此,以前的JDK应该依靠try-catch块,即使他们觉得笨重.

java – 如何验证是否抛出异常的更多相关文章

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. js中‘!.’是什么意思

  3. InnoDB 和 MyISAM 引擎恢复数据库,使用 .frm、.ibd文件恢复数据库

  4. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  5. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  6. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  7. 宝塔Linux的FTP连接不上的解决方法

    宝塔Linux的FTP连接不上的解决方法常见的几个可能,建议先排查。1.注意内网IP和外网IP2.检查ftp服务是否启动 (面板首页即可看到)3.检查防火墙20端口 ftp 21端口及被动端口39000 - 40000是否放行 (如是腾讯云/阿里云等还需检查安全组)4.是否主动/被动模式都不能连接5.新建一个用户看是否能连接6.修改ftp配置文件 将ForcePassiveIP前面的#去掉 将19

  8. 扩展element-ui el-upload组件,实现复制粘贴上传图片文件,带图片预览功能

  9. 微信小程序canvas实现水平、垂直居中效果

    这篇文章主要介绍了小程序中canvas实现水平、垂直居中效果,本文图文实例代码相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

  10. 使用HTML5做的导航条详细步骤

    这篇文章主要介绍了用HTML5做的导航条详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部