使用JUnit的ExpectedException和@Rule测试自定义异常

异常测试

为什么要测试异常流? 就像所有代码一样,测试覆盖率会在代码和应该生成的业务功能之间写一个合同,从而为您提供代码的有效文档 ,以及增加的尽早且经常强调功能的功能。 我不会介绍测试的许多好处,而是只关注异常测试。

有很多方法可以测试从一段代码引发的异常流。 假设您有一个受保护的方法,该方法要求参数不为null。 您将如何测试该状况? 引发异常时,如何防止JUnit报告失败? 该博客涵盖了几种不同的方法使用JUnit的的ExpectedException使用JUnit的@rule功能实现的高潮。

“旧”方式

在不久的将来,测试异常的过程需要大量的样板代码,您可以在其中启动try / catch块,如果代码未产生预期的行为,则报告失败,然后捕获异常以查找异常。具体类型。 这是一个例子:

public class MyObjTest {@Testpublic void getNameWithNullValue() {try {MyObj obj = new MyObj();myObj.setName(null);fail('This should have thrown an exception');} catch (IllegalArgumentException e) {assertThat(e.getMessage().equals('Name must not be null'));}}
}

从这个旧示例中可以看到,测试用例中的许多行只是为了支持缺少专门测试异常处理的功能。 使用try / catch方法的一个好处是可以测试特定消息和预期异常上的任何自定义字段 。 我们将通过JUnit的ExpectedException和@Rule注释进一步探讨这一点。

JUnit添加了预期的异常

JUnit通过添加@Test注释字段“ expected”来响应用户对异常处理的需求。 目的是,如果引发的异常类型与注释中存在的异常类匹配,则整个测试用例将通过。

public class MyObjTest {@Test(expected = IllegalArgumentException.class)public void getNameWithNullValue() {MyObj obj = new MyObj();myObj.setName(null);}
}

从较新的示例中可以看到,样板代码要少得多,并且测试非常简洁,但是存在一些缺陷 。 主要缺陷是测试条件太宽泛。 假设签名中有两个变量,并且两个变量都不能为null,那么如何知道为IllegalArgumentException抛出了哪个变量呢? 当您扩展了Throwable并需要检查字段的存在时会发生什么? 在继续阅读时,请记住这些,随后将有解决方案。

JUnit @Rule和ExpectedException

如果查看前面的示例,可能会看到期望抛出IllegalArgumentException,但是如果您有一个自定义异常,该怎么办? 如果要确保该消息包含特定的错误代码或消息怎么办? 这是JUnit真正出色的地方,它提供了专门为异常测试量身定制的JUnit @Rule对象。 如果您不熟悉JUnit @Rule,请在此处阅读文档 。

ExpectedException

JUnit提供了一个JUnit类ExpectedException,该类旨在用作@Rule。 ExpectedException允许您的测试声明预期会出现异常,并为您提供一些基本的内置功能来清楚地表达预期的行为。 与@Test(expected)批注功能不同,ExpectedException类允许您通过Hamcrest匹配器库测试特定的错误消息和自定义字段。

JUnit的ExpectedException的示例

import org.junit.rules.ExpectedException;public class MyObjTest {@Rulepublic ExpectedException thrown = ExpectedException.none();@Testpublic void getNameWithNullValue() {thrown.expect(IllegalArgumentException.class);thrown.expectMessage('Name must not be null');MyObj obj = new MyObj();obj.setName(null);}
}

如前所述,该框架允许您测试特定消息,以确保在测试专门寻找的情况下抛出异常。 当怀疑多个参数的可空性时,这将非常有用。

自定义字段

可以说,ExpectedException框架最有用的功能是能够使用Hamcrest匹配器测试您的自定义/扩展异常。 例如,您有一个自定义/扩展的异常将被抛出到一个方法中,并且该异常内部有一个“ errorCode”。 如何在不从上面列出的try / catch块中引入样板代码的情况下测试该功能? 定制匹配器怎么样!

可以从以下网址获得此代码: https : //github.com/mike-ensor/custom-exception-testing

解决方案:首先是测试用例

import org.junit.rules.ExpectedException;public class MyObjTest {@Rulepublic ExpectedException thrown = ExpectedException.none();@Testpublic void someMethodThatThrowsCustomException() {thrown.expect(CustomException.class);thrown.expect(CustomMatcher.hasCode('110501'));MyObj obj = new MyObj();obj.methodThatThrowsCustomException();}
}

解决方案:自定义匹配器

import com.thepixlounge.exceptions.CustomException;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;public class CustomMatcher extends TypeSafeMatcher<CustomException> {public static BusinessMatcher hasCode(String item) {return new BusinessMatcher(item);}private String foundErrorCode;private final String expectedErrorCode;private CustomMatcher(String expectedErrorCode) {this.expectedErrorCode = expectedErrorCode;}@Overrideprotected boolean matchesSafely(final CustomException exception) {foundErrorCode = exception.getErrorCode();return foundErrorCode.equalsIgnoreCase(expectedErrorCode);}@Overridepublic void describeTo(Description description) {description.appendValue(foundErrorCode).appendText(' was not found instead of ').appendValue(expectedErrorCode);}
}

注意:请访问https://github.com/mike-ensor/custom-exception-testing以获取可用的Hamcrest Matcher,JUnit @Rule和ExpectedException的副本。

在那里,您可以快速概览一下测试代码引发的异常的不同方法,以及从自定义异常类中测试特定消息和字段的能力。 请具体说明您的测试用例,并尝试针对您为测试设置的确切用例,请记住,测试可以避免引入副作用漏洞!

祝您编程愉快,别忘了分享!

参考:在Mike的站点博客上,从JCG合作伙伴 Mike 那里 ,使用JUnit的ExpectedException和@Rule测试自定义异常 。


翻译自: https://www.javacodegeeks.com/2012/10/testing-custom-exceptions-with-junits.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线程的工具类(Exchange)

public class Exchanger<V>extends Object 可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange 方法&#xff0c;与伙伴线程进行匹配&#xff0c;并且在返回时接收其伙伴的对象。Exchanger 可能被视为 SynchronousQueue 的双向形…

js 判断浏览器是否64位

js判断是否64位 浏览器 navigator.userAgent.match(/x64/i); 转载于:https://www.cnblogs.com/fanlinglong/p/7298733.html

linux ss 软件,linux ss 网络状态工具

ss是Socket Statistics的缩写查看网络状态&#xff0c;经常用的命令&#xff1a; watch ss -lntss命令用于显示socket状态. 他可以显示PACKET sockets, TCP sockets, UDP sockets, DCCP sockets, RAW sockets, Unix domain sockets等等统计. 它比其他工具展示等多tcp和state信…

Lambda项目:迈向多核及超越

周一下午在JavaOne 2011的希尔顿旧金山大宴会厅B上做了“ Project Lambda&#xff1a;迈向多核和超越”&#xff08;会议27400&#xff0c;不要与Brian Goetz的同名演讲相混淆&#xff09; 的演示 。大宴会厅关闭&#xff0c;这是一个非常大型的非主题演讲场地&#xff0c;并且…

Python 06-字典

字典是一种key-value的数据类型&#xff0c;就像日常用的字典&#xff0c;通过字母或者笔画来查找对应页的详细内容。 字典是无序的&#xff0c;没有顺序。因为有key。 info {stu1001:wang er,stu1002:zhang san,stu1003:li si } print(info)#打印字典所有kv print(info[stu10…

hashMap 源码解读理解实现原理和hash冲突

hashMap 怎么说呢。 我的理解是 外表是一个set 数组&#xff0c;无序不重复 。 每个set元素是一个bean &#xff0c;存着一对key value 看看代码吧 package test;import java.util.HashMap; import java.util.Map.Entry;public class HashMaptest {public static void main(Str…

浙江大学linux网络通信,浙江大学钟财军副教授——“Wireless Powered Communication Networks”...

2016年5月17日&#xff0c;浙江大学钟财军副教授应徐正元教授邀请在中科大西区科技实验楼东楼十层1011会议室做了一场题为“Wireless Powered Communication Networks”的学术报告。报告会由龚晨教授主持&#xff0c;共50余名师生参加。此次报告会得到了“中科院无线光电通信重…

自定义Spring Data JPA存储库

Spring Data是一个非常方便的库。 但是&#xff0c;由于该项目是一个相当新的项目&#xff0c;因此功能不佳。 默认情况下&#xff0c;Spring Data JPA将基于SimpleJpaRepository提供DAO的实现。 在最近的项目中&#xff0c;我开发了一个定制的存储库基类&#xff0c;以便可以在…

[基础]PeopleSoft中的作业和调度作业集合定义

PeopleSoft进程调度器可以使一个或多个进程作为一个组。这个组在PeopleSoft中被称为作业(Job)。 PeopleSoft进程被定义为单个任务&#xff0c;程序或例程&#xff0c;例如cobol程序或AE程序或客户端运行的SQR。 作业由一个或多个相同或不同类型的进程组成&#xff0c;他们作为一…

体验 WebFont,网页上的艺术字

在最新项目中&#xff0c;由于要频繁使用艺术字&#xff0c;而用户设备没有此字体&#xff0c;因此以往的经验都是使用图片...所以在同事的瞩目期许之下&#xff0c;我开始实验研究这个问题的解决方案1. 直接使用字体文件font-face {font-family: xxxx;src: url(../img/汉仪秀英…

linux文件分别打包命令,Linux文件打包命令

15.1 gzipgzip(1)是GNU的压缩程序。它只对单个文件进行压缩。基本用法如下&#xff1a;$ gzip filename程序执行以后&#xff0c;文件名会变成filename.gz&#xff0c;而且一般情况下大小会比原文件要小。注意&#xff0c;程序并不新建一个新的文件filename.gz,而是将filename变…

Play 2.0框架和XA交易

XA事务非常有用&#xff0c;而且开箱即用&#xff0c;今天的Play 2.0不支持它们。 在这里&#xff0c;我展示了如何添加该支持&#xff1a; 首先&#xff0c;介绍一些XA有用的示例&#xff1a; –如果您使用来自两个不同persistence.xml的实体&#xff0c;则JPA使用两个物理连…

java代码注释规范

java代码注释规范 一、规范存在的意义 应用编码规范对于软件本身和软件开发人员而言尤为重要&#xff0c;有以下几个原因&#xff1a;1、好的编码规范可以尽可能的减少一个软件的维护成本 , 并且几乎没有任何一个软件&#xff0c;在其整个生命周期中&#xff0c;均由最初的开…

win10 hyper-v 虚拟机ping不通宿主机问题

在Windows10 Hyper-V 中安装 Linux (Centos6.9)虚拟机无法 ping 通宿主机 这种情况下关闭 Windows 防火墙就能ping通了&#xff0c;当然关闭防火墙不安全。所以需要 做以下步骤: 控制面板-》系统和安全-》Windows防火墙-》高级设置-》入站规则 启用下图被红框选中的两个选…

linux方法参数,Linux的sysctl 命令 参数

Linux内核通过/proc虚拟文件系统向用户导出内核信息&#xff0c;用户也可以通过/proc文件系统或通过sysctl命令动态配置内核。比如&#xff0c;如果我们想启动NAT&#xff0c;除了加载模块、配置防火墙外&#xff0c;还需要启动内核转发功能。我们有三种方法&#xff1a;1. 直接…

Java枚举:您拥有优雅,优雅和力量,这就是我所爱!

当Java 8即将面世时&#xff0c;您确定您对Java 5中引入的枚举很了解吗&#xff1f; Java枚举仍然被低估了&#xff0c;很可惜&#xff0c;因为它们比您想象的要有用&#xff0c;它们不仅仅用于通常的枚举常量&#xff01; Java枚举是多态的 Java枚举是可以包含行为甚至数据的…

C#删除和清空文件夹的程序

/// <summary>/// 清空指定的文件夹&#xff0c;但不删除文件夹/// </summary>/// <param name"dir"></param>private void DeleteFolder(string dir){foreach (string d in Directory.GetFileSystemEntries(dir)){if (File.Exists(d)){try{…

2)网页请求顺序

&#xff08;1&#xff09;分析浏览器访问一个网页的完整流程逻辑过程&#xff1a;http&#xff1a;//www.abc.com/def/ 转载于:https://www.cnblogs.com/xiaoyoucai/p/7306246.html

JavaOne 2012:非阻塞数据结构如何工作?

当我查看今天的日程安排时&#xff0c;我感到有些惊讶&#xff0c;并指出我目前计划今天参加的所有会议都在希尔顿举行。 当我意识到JavaOne演示文稿中大约有一半是在希尔顿酒店中并且似乎按路线大致定位时&#xff0c;这变得有些不足为奇了。 Tobias Lindaaker &#xff08; 新…

c语言箭头指针的作用,C语言中,结构体成员变量的点和箭头

C语言中&#xff0c;调用成员变量用点还是用箭头&#xff0c;取决于当前的ID是指针还是结构体本身。如&#xff1a;typedef struct {float height;float weight;} Person;int main(int argc, char *argv[]) {Person jiushen;Person *lengleng (Person *)malloc(sizeof(Person)…