Junit测试预期异常

开发人员常常使用单元测试来验证的一段儿代码的操作,很多时候单元测试可以检查抛出预期异常( expected exceptions)的代码。在Java语言中,JUnit是一套标准的单元测试方案,它提供了很多验证抛出的异常的机制。本文就探讨一下他们的优点。

  我们拿下面的代码作为例子,写一个测试,确保canVote() 方法返回true或者false, 同时你也能写一个测试用来验证这个方法抛出的IllegalArgumentException异常。

  public class Student {

  public boolean canVote(int age) {

  if (i<=0) throw new IllegalArgumentException("age should be +ve");

  if (i<18) return false;

  else return true;

  }

  }

  (Guava类库中提供了一个作参数检查的工具类--Preconditions类,也许这种方法能够更好的检查这样的参数,不过这个例子也能够检查)。

  检查抛出的异常有三种方式,它们各自都有优缺点:

  1.@Test(expected…)

  @Test注解有一个可选的参数,"expected"允许你设置一个Throwable的子类。如果你想要验证上面的canVote()方法抛出预期的异常,我们可以这样写:

  @Test(expected = IllegalArgumentException.class)

  public void canVote_throws_IllegalArgumentException_for_zero_age() {

  Student student = new Student();

  student.canVote(0);

  }

  简单明了,这个测试有一点误差,因为异常会在方法的某个位置被抛出,但不一定在特定的某行。

  2.ExpectedException

  如果要使用JUnit框架中的ExpectedException类,需要声明ExpectedException异常。

  @Rule

  public ExpectedException thrown= ExpectedException.none();

  然后你可以使用更加简单的方式验证预期的异常。

  @Test

  public void canVote_throws_IllegalArgumentException_for_zero_age() {

  Student student = new Student();

  thrown.expect(NullPointerException.class);

  student.canVote(0);

  }

  或者可以设置预期异常的属性信息。

  @Test

  public void canVote_throws_IllegalArgumentException_for_zero_age() {

  Student student = new Student();

  thrown.expect(IllegalArgumentException.class);

  thrown.expectMessage("age should be +ve");

  student.canVote(0);

  }

 除了可以设置异常的属性信息之外,这种方法还有一个优点,它可以更加精确的找到异常抛出的位置。在上面的例子中,在构造函数中抛出的未预期的(unexpected) IllegalArgumentException 异常将会引起测试失败,我们希望它在canVote()方法中抛出。

  从另一个方面来说,如果不需要声明就更好了

  @Rule

  public ExpectedException thrown= ExpectedException.none();

  它就像不需要的噪音一样,如果这样就很好了

  expect(RuntimeException.class)

  或者:

  expect(RuntimeException.class, “Expected exception message”)

  或者至少可以将异常和信息当做参数传进去

  thrown.expect(IllegalArgumentException.class, “age should be +ve”);

  3.Try/catch with assert/fail

  在JUnit4之前的版本中,使用try/catch语句块检查异常


@Test

public void canVote_throws_IllegalArgumentException_for_zero_age() {

Student student = new Student();

try {

student.canVote(0);

} catch (IllegalArgumentException ex) {

assertThat(ex.getMessage(), containsString("age should be +ve"));

}

fail("expected IllegalArgumentException for non +ve age");

}

  尽管这种方式很老了,不过还是非常有效的。主要的缺点就是很容易忘记在catch语句块之后需要写fail()方法,如果预期异常没有抛出就会导致信息的误报。我曾经就犯过这样的错误。

  总之,这三种方法都可以测试预期抛出的异常,各有优缺点。对于我个人而言,我会选择第二种方法,因为它可以非常精确、高效的测试异常信息。

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-02 18:32:28

Junit测试预期异常的相关文章

JUnit测试框架的使用经验分享

1.学习Junit框架的使用 可通过以下两个示例进行学习. A.Junit使用方法示例1 1)把Junit引入当前项目库中 新建一个 Java 工程-coolJUnit,打开项目coolJUnit 的属性页 -> 选择"Java Build Path"子选项 -> 点选"Add Library-"按钮 -> 在弹出的"Add Library"对话框中选择 JUnit,并在下一页中选择版本 Junit 4 后点击"Fin

《JUnit实战(第2版)》—— 1.6 使用JUnit测试

1.6 使用JUnit测试 JUnit实战(第2版)JUnit拥有许多功能,可以使编写.运行测试更加容易.通过本书,你将可以了解到这些功能在实际中的各种运用. 针对每个单元测试,单独测试类实例和类加载器,以避免副作用.JUnit注释提供了资源初始化和回收方法:@Before.@BeforeClass.@After和@AfterClass.各种不同的assert方法使得检查测试结果更加简单.与各种流行工具(如Ant和Maven)的整合,以及与流行IDE(如Eclipse.NetBeans.Inte

《JUnit实战(第2版)》—第1章1.6节使用JUnit测试

1.6 使用JUnit测试JUnit实战(第2版)JUnit拥有许多功能,可以使编写.运行测试更加容易.通过本书,你将可以了解到这些功能在实际中的各种运用. 针对每个单元测试,单独测试类实例和类加载器,以避免副作用.JUnit注释提供了资源初始化和回收方法:@Before.@BeforeClass.@After和@AfterClass.各种不同的assert方法使得检查测试结果更加简单.与各种流行工具(如Ant和Maven)的整合,以及与流行IDE(如Eclipse.NetBeans.Intel

悬赏如何junit测试返回值void的输出验证码图片功能的servlet!

问题描述 悬赏如何junit测试返回值void的输出验证码图片功能的servlet! 刚接触到验证码生成算法,由于楼主刚入职职场,刚接触junit测试,知道junit是白盒子测试,也只会用代用返回值的测试.现在我要写一个生成验证码的serlvet,此serlvet可以向客户端返回一个验证码的jpg图片.请问如果用junit来测试这个类的生成验证码功能是否生效?我知道难度可能有点大,所以希望大神耐心解答,50分献上! public class ValidateCodeServlet extends

图片-Java SSH整合框架.tomcat能正常跑,没问题.用junit测试却报配置错误.

问题描述 Java SSH整合框架.tomcat能正常跑,没问题.用junit测试却报配置错误. 配置如第一张图. 报错如下面两张. new ClassPathXmlApplicationContext("applicationContext.xml");junit初始化配置时出现的问题.最后导致beanFactory.containsBean("Sys_UserDao")为fasle 解决方案 不是已经说了没有引人hibernate属性文件啊, 解决方案二: 你的

Junit测试框架

最简单的例子介绍Junit测试框架 public class Person { public void run() { System.out.println("run!!!"); } public void eat() { System.out.println("eat!!!"); } public static void main(String[] args){ System.out.println("miao"); } } import or

spring junit测试

利用spring的mock类进行单元测试: spring框架提供了大量测试的mock类,包括与jndi,porlet,web应用相关的mock类.尤其是web应用相关 的mock类,可以大大提高web组件测试的方便性. 打开spring的下载包的mock文件夹(路径...mock\org\springframework\mock\web),就发觉有如下几个 文件: MockHttpServletRequest:是HttpServletRequest接口的mock实现,用来模拟客户端的HTTP请求

TestNG官方文档中文版(9)-重复失败测试,junit测试,jdk1.4支持

5.10 - Rerunning failed tests 套件中的测试失败时,每次testNG都会在输出目录中创建一个名为testng-failed.xml 的文件.这个xml文件包含只重新运行这些失败的测试方法的必要信息,容许只运行这些 失败的测试而不必运行全部测试.因此,一种典型的情况将是这样: java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs testng.xml java -classpat

JUnit测试小记

今天说说junit测试技术,其实这个技术大部分人都听过,只是有些人没用过而已,这东西说起来也很容易,但是确实软件开发过程中必不可少的一门技术,对于一些不规范的小公司也许产品的发布不经过测试,但是对于大型的软件开发的时候,这技术往往是必不可少的,因为任何一个小地方出错都可能是一个很难发现的,但是junit技术这个单元测试技术让我们能边开发边测试,使我们的最终产品出错的几率达到最少. 我今天讲的例子,开发环境是myeclipse6.0,在这个开发环境中其实已经集成了我们所要的JUnit测试相关的类,