当前位置: 首页 > 编程笔记 >

Java中的异常测试框架JUnit使用上手指南

陆俊捷
2023-03-14
本文向大家介绍Java中的异常测试框架JUnit使用上手指南,包括了Java中的异常测试框架JUnit使用上手指南的使用技巧和注意事项,需要的朋友参考一下

JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即白盒测试。该项目主页:http://www.junit.org/

使用JUnit时,主要都是通过继承TestCase类别来撰写测试用例,使用testXXX()名称来撰写单元测试。

用JUnit写测试真正所需要的就三件事:

1.  一个import语句引入所有junit.framework.*下的类。

2.  一个extends语句让你的类从TestCase继承。

3.  一个调用super(string)的构造函数。

功能类MathTool

package com.zj.c01;
public class MathTool { 
 public static int gcd(int num1, int num2) { 
  int r = 0; 
  while (num2 != 0) { 
   r = num1 % num2; 
   num1 = num2; 
   num2 = r; 
  } 
  return num1; 
 } 
} 

测试类MathToolTest

package com.zj.c01;
import junit.framework.TestCase; 
 
public class MathToolTest extends TestCase { 
 public MathToolTest(String name) { 
  super(name); 
 } 
 
 public void testGcd() { 
  assertEquals(5, MathTool.gcd(10, 5)); 
 } 
} 

 我们在用 JUnit 测试方法异常的时候,最容易想到的办法就是用 try…catch 去捕获异常,需要断言以下几个条件:
  1. 确实抛出的异常
  2. 抛出异常的 Class 类型
  3. 抛出异常的具体类型,一般检查异常的 message 属性中包含的字符串的断定
  所以常用的代码你可能会这么写:

    @Test
    public void testBizException()
{
	    try{
		    Password.validate( "123" );
		    fail( "No exception thrown." );
		   
	}catch ( Exception ex ) {
		    assertTrue( ex instanceof BizException );
		    assertTrue( ex.getMessage().contains( "error" ) );
		   
	}
	   
}


  这里被测试的方法是 Password.validate() 方法是否抛出了相应的异常,注意这里别漏 try 中的
  fail(“No Exception thrown.”)
  代码行,不然如果被测试的方法如果没有抛出异常的话,这个用例是通过的,而你预期的是要抛出异常的。
  在 JUnit 4 中,大可不必如此这般的去测试方法异常。虽然这样也能测定出是否执行出预期的异常来,但它仍有弊端,接下来会一对比就知道了,try…catch 的方法,JUnit 无法为你提示出详细的断言失败原因。
  那么来看看自从 JUnit 4 后可以怎么去测试异常呢?用 @Test(execpted=Exception.class) 注解就行,参考如下代码:

    @Test( expected = BizException.class )
    public void testBizException()
{
     Password.validate( null );
    
}


  如果被测试的方法有抛出 BizException类型便是断言成功,对了 @Test(expected = BizException.class) 只能判断出异常的类型,并无相应的注解能断言出异常的更具体的信息,即无法判定抛出异常的 message 属性。
  那么,有时候我们会在一个方法中多次抛出一种类型的异常,但原因不同,即异常的 message 信息不同,比如出现 BizException 时会有以下两种异常:

  new BizException(“Password must contains at least 6 letters.”)
  new BizException(“Password length less than 15 letters”)

  这就要有办法去断言异常的 message 了,针对于此,自 JUnit 4.7 之后又给了我们更完美的选择,就是下面的代码:

    @Rule
    public ExpectedException expectedEx = ExpectedException.none();
    @Test
    public void testBizException() throws InvalidPasswordException
{
	    expectedEx.expect( BizException.class );
	    expectedEx.expectMessage( "required" );
	    Password.validate( "" );
	   
}


  上面代码需重点关注几个:
  1. @Rule 注解的 ExpectedException 变量声明,它必须为 public
  2. @Test 处,不能写成 @Test(expected=BizException.class),否则不能正确测试,也就是
  @Test(expected=BizException.class) 和测试方法中的 expectedEx.expectXxx() 方法是不能同时并存的
  3. expectedEx.expectMessage() 中的参数是 Matcher 或 subString,就是说可用正则表达式判定,或判断是否包含某个子字符串
  4. 再就是有一点很重,把被测试方法写在 expectedEx.expectXxx() 方法后面,不然也不能正确测试的异常
  5. 最后一个是,只要测试方法直接抛出被测试方法的异常即可,并不影响你所关心的异常
  前面说到用 try…catch 的办法也能正确测试到异常,@Test(expected=…) 或 @Rule 与 try…catch 的方法对比有什么好处呢,显然用 JUnit 4 推荐的方法简洁明了。再来看测试失败时 JUnit 会为你提示什么呢?
  try…catch 测试异常失败时,得到的提示:
  无异常时:

  java.lang.AssertionError: No exception thrown.
  at org.junit.Assert.fail(Assert.java:91)
  at cc.unmi.PasswordTest.passwordLengthLessThan6LettersThrowsException(PasswordTest.java:20)

  异常类型不对或异常的 message 不对时:

  java.lang.AssertionError:
  at org.junit.Assert.fail(Assert.java:91)
  at org.junit.Assert.assertTrue(Assert.java:43)
  at org.junit.Assert.assertTrue(Assert.java:54)
  at cc.unmi.PasswordTest.passwordLengthLessThan6LettersThrowsException(PasswordTest.java:22)

  上面能提供给我们的定位错误的帮助不是特别大
  再看 @Test(expected=BizException.class) 时测试失败时的提示:

  java.lang.AssertionError: Expected exception: cc.test.BizException
  at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:32)
  at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:110)

  用 @Rules ExpectedException方式来测试异常,失败时的提示:

  java.lang.AssertionError:
  Expected: (exception with message a string containing “YES. required” and an instance of java.lang.NullPointerException)
  got:
  at org.junit.Assert.assertThat(Assert.java:778)
  at org.junit.Assert.assertThat(Assert.java:736)
  at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:114)

  特别是 @Rules ExpectedException 方法时为何测试失败提示的清清楚楚。期望什么异常,异常 message 中含何字符串,实际上确得到什么类型的异常,异常中 message 是什么。有了这,你一看到就知道怎么去修补你的程序

 类似资料:
  • 我构建了一个有3个属性的帐户类:余额、所有者、acctNo。帐户类有2个构造函数,一个接受3个属性,一个不接受数据。帐户类有设置和获取方法以及存款和取款方法。 我还构建了一个类,该类从类扩展而来。将此类修改为类后,取款方法或此方法尝试将余额设置为零以下,将抛出。 JUnit测试人员修改测试方法,将尝试提取超过当前余额的可用,所以做测试方法。我需要修改JUnit测试透支帐户,以便它捕获异常,并捕获。

  • 本文向大家介绍Node.js的Express框架使用上手指南,包括了Node.js的Express框架使用上手指南的使用技巧和注意事项,需要的朋友参考一下 Express介绍 npm提供了大量的第三方模块,其中不乏许多Web框架,比如我们本章节要讲述的一个轻量级的Web框架 ——— Express。 Express是一个简洁、灵活的node.js Web应用开发框架, 它提供一系列强大的功能,比如

  • 问题内容: 我真的是java的新手。 我正在构造函数上运行一些JUnit测试。构造函数是这样的:如果为其参数之一赋予null或空字符串,则应该抛出异常。 当我在JUnit中使用null或空字符串参数测试此构造函数时,即使我几乎100%确信将此类参数传递给它时,构造函数方法确实会引发异常,我也会看到一条红色的条。 如果该方法以预期的方式引发异常,则JUnit中是否应该没有绿色的条形?还是当异常抛出按

  • 问题内容: 编辑:目前没有JUnit 4。 嗨,您好, 我对使用JUnit进行“智能”异常测试有疑问。目前,我这样做是这样的: 如您所见,对于每个应该引发异常的函数,我都需要一个try / catch块。似乎不是执行此操作的好方法-还是没有可能减少try / catch的使用? 问题答案: 我建议您需要分解为多个单独的测试。各个try / catch块似乎彼此非常独立。您可能还希望将通用初始化逻辑

  • 尝试让JUnit与mockito测试一起工作,并在我的测试中获得NPE。我想验证一下,当调用时,紧接着调用了方法。我觉得奇怪的一个问题是,在Mockito上。验证(registrationServiceImpl,Mockito.times(1))。创建注册人(registrationDTO) 方法?IntelliJ只建议界面中的方法? 我的测试代码如下: 下面是我正在测试的代码:

  • 我应该如何测试异常?我可以mock connector并且我可以赋予它抛出异常的行为,但是我不明白下一步该怎么做。