`

JUnit4 新特性

阅读更多

JUnit 4是JUnit框架有史以来的最大改进,其主要目标便是利用Java 5的Annotation特性简化测试用例的编写。让我们看看如何使用JUnit 4来进行Unit测试。

请注意:本文主要介绍JUnit 4的最新特性和用法,并不会讲解Unit测试的基础。如果你对JUnit框架还不熟悉,请先参考“在Eclipse中使用JUnit”一文,学习如何编写JUnit测试。

我们使用的开发环境是Eclipse 3.2,它已经自带了JUnit 4.1,你需要将JUnit 4 Library添加到项目用到的Library中。另外,必须使用JDK 5.0或更高版本。

要在Eclipse环境之外运行JUnit,需要下载JUnit 4.1,具体请访问JUnit.org。

我们先看一个简单的Math类:

ActionScript/Java代码
  1. package com.crackj2ee.junit4;  
  2. public class Math {  
  3.   
  4.    public int abs(int value) {  
  5. return value>=0 ? value : (-value);  
  6.    }  
  7.   
  8.    public int div(int a, int b) {  
  9. return a / b;  
  10.    }  
  11.   
  12.    /** 
  13.    * BUG: if b less than 0! 
  14.    */  
  15.    public float exp(int a, int b) {  
  16. float r = 1;  
  17. for(int i=0; i<b; i++)  
  18.        r = r * a;  
  19. return r;  
  20.    }  
  21. }  



注意exp()方法是有Bug的,如果传入参数2, -1,则期待的返回值应为0.5F,但实际返回值为1.0F。

下面我们看看传统的JUnit的TestCase:

ActionScript/Java代码
  1. public class MathTest extends TestCase {  
  2.   
  3.    public void setUp() { super.setUp(); }  
  4.    public void tearDown() { super.tearDown(); }  
  5.   
  6.    public void testAbs() { assertTrue(true); }  
  7.    public void testDiv() {...}  
  8.    public void testExp() {...}  
  9.   
  10. }  


JUnit依赖反射来执行每个以test开头的方法。然而,在最新的JUnit 4中,由于有了Annotation的支持,我们的测试方法不需要再以testXxx标识了,而是写上一个@Test标注即可。例如:

@Test public void doAbs() {...}
甚至MathTest类也不必继承自TestCase。你也许会想到,不继承自TestCase就无法调用assertXxx方法了,正因为如此,所有的 assertXxx方法全部以静态方法被放入了Assert类,使用Assert.assertXxx()调用。如果使用

import static org.junit.Assert.*;
则原有的代码不必改动。

setUp()和tearDown()方法也依赖@Before和@After标记,这样做的最大的好处是在继承体系内不必担心忘记了在setUp()方 法中调用父类的super.setUp()方法,JUnit框架会自动处理父类的@Before和@After标记的方法。

并且,JUnit框架对@Before和@After的调用顺序类似于类的构造方法和析构方法,即@Before按照父类到子类的顺序调用,@After则相反,这样保证了资源的正确获取和释放。

当然,不再强迫必须使用setUp和tearDown作为方法名,可以使用更有意义的方法名,例如:initDatabase()和closeDatabase(),只要它们被标注了@Before和@After即可。

来看看使用Annotation的MathTest:

ActionScript/Java代码
  1. package com.crackj2ee.junit4;  
  2.   
  3. import static org.junit.Assert.*;  
  4.   
  5. import org.junit.*;  
  6.   
  7. public class MathTest  
  8. {  
  9.   
  10.     public MathTest()  
  11.     {  
  12.         System.out.println("new MathTest instance.");  
  13.     }  
  14.   
  15.     @Before public void setUp()throws Exception  
  16.     {  
  17.         System.out.println("call @Before before a test method");  
  18.     }  
  19.   
  20.     @After public void tearDown()throws Exception  
  21.     {  
  22.         System.out.println("call @After after a test method");  
  23.     }  
  24.   
  25.     @Test public void doAbs()  
  26.     {  
  27.         Math math = new Math();  
  28.         assertEquals(200, math.abs(200));  
  29.         assertEquals(100, math.abs( - 100));  
  30.         assertEquals(0, math.abs(0));  
  31.     }  
  32.   
  33.     @Test public void doDiv()  
  34.     {  
  35.         Math math = new Math();  
  36.         assertEquals(5, math.div(10020));  
  37.         assertEquals(4, math.div(10021));  
  38.     }  
  39.   
  40.     @Test(expected = ArithmeticException.class)public void doDiv0()  
  41.     {  
  42.         new Math().div(1270);  
  43.     }  
  44.   
  45.     @Test(timeout = 1)public void doLongTimeTask()  
  46.     {  
  47.         double d = 0;  
  48.         for (int i = 1; i < 10000000; i++)  
  49.             d += i;  
  50.     }  
  51.   
  52.     @Test public void testExp()  
  53.     {  
  54.         Math math = new Math();  
  55.         assertEquals(32f, math.exp(25), 0.001f);  
  56.         assertEquals(1f, math.exp(20), 0.001f);  
  57.         assertEquals(0.5f, math.exp(2, ( - 1)), 0.001f);  
  58.     }  
  59.   
  60. }  


对测试异常,JUnit 4可以用expected=Exception.class来期待一个预期的异常,而不必编写

ActionScript/Java代码
  1. try {  
  2.     ...  
  3.     fail("No exception");  
  4. }  
  5.     catch(Exception e) {  
  6.     // OK!  
  7. }  


来看看doDiv0测试,我们期待一个除数为0的ArithmeticException,因此编写如下测试方法:

ActionScript/Java代码
  1. @Test(expected=ArithmeticException.class)  
  2. public void doDiv0() {  
  3.    new Math().div(1270);  
  4. }  


对于非常耗时的测试,@Test还有一个timeout来标识该方法最长执行时间,超过此时间即表示该测试方法失败:

ActionScript/Java代码
  1. @Test(timeout=1)  
  2. public void doLongTimeTask() {  
  3.    double d = 0;  
  4.    for(int i=1; i<10000000; i++)  
  5.       d+=i;  
  6. }  


以上方法若执行时间超过1ms则测试失败,由于依赖CPU的执行速度,在不同的机器上测试结果也不同。

JUnit 4另一个较大的变化是引入了@BeforeClass和@AfterClass,它们在一个Test类的所有测试方法执行前后各执行一次。这是为了能在 @BeforeClass中初始化一些昂贵的资源,例如数据库连接,然后执行所有的测试方法,最后在@AfterClass中释放资源。

正如你能想到的,由于@BeforeClass和@AfterClass仅执行一次,因此它们只能标记静态方法,在所有测试方法中 共享的资源也必须是静态引用:

ActionScript/Java代码
  1. private static Object dbConnection;  
  2.   
  3. @BeforeClass  
  4. public static void setUpBeforeClass() throws Exception {  
  5.    System.out.println("call @BeforeClass and init database connection");  
  6.    dbConnection = new Object();  
  7. }  
  8.   
  9. @AfterClass  
  10. public static void tearDownAfterClass() throws Exception {  
  11.    System.out.println("call @AfterClass to release database connection");  
  12.    dbConnection = null;  
  13. }  


最后执行测试用例,可以看到结果:

各个方法执行顺序如下:

call @BeforeClass and init database connection

new MathTest instance.
call @Before before a test method
call @After after a test method

new MathTest instance.
call @Before before a test method
call @After after a test method

...

call @AfterClass to release database connection

可以看到,@BeforeClass是在实例化MathTest之前调用的,因此不能在构造方法中初始化共享资源。

最后需要注意的是由于Java 5的自动Box/Unbox特性,在调用assertEquals()时要特别注意,如果你传入:

assertEquals(100F, 100);

则按照自动Box变为:

assertEquals(new Float(100F), new Integer(100));

测试失败,因为Float类和Integer类不是同一类型。

因此要特别注意float和double的测试。事实上对float和double应使用

assertEquals(float, float, float delta);
assertEquals(double, double, double delta);

delta指定了两个作比较的浮点数的相差范围,在此范围内的两个浮点数将认为相等。可以传入一个很小的数例如0.0001F。 

JUnit 4非常适合使用Java 5的开发人员,但是无法在Java 1.4中获得这些好处,并且,也不与以前的版本兼容。因此,如果你正在使用Java 5,就可以考虑使用JUnit 4来编写测试。

分享到:
评论

相关推荐

    myEclipse下使用Junit

    本资源将指导读者如何在myEclipse中使用Junit,包括准备工作、使用Junit进行测试、Junit断言方法、Junit 4新特性等方面的内容。 一、准备工作 在myEclipse中使用Junit需要进行一些准备工作。首先,需要导入Junit的...

    junit4 jar包

    JUnit4还支持测试套件(`@RunWith(Suite.class)`)、参数化测试(`@Parameters`)、定时器(`@Test(timeout = XXX)`)和假设(`Assume`类)等高级特性,这些都极大地增强了测试的灵活性和覆盖率。此外,JUnit4可以与...

    junit4学习文档

    JUnit4 是 JUnit 测试框架的一个重大更新版本,它充分利用了 Java 5 的注解(Annotation)特性来简化测试用例的编写过程。注解是一种元数据,用于描述程序中的元素如类、方法或变量的作用。与传统的关键字(如 ...

    JUnit4JUnit4JUnit4(文档)

    JUnit4引入了许多改进和新特性,极大地提升了测试的灵活性和效率。下面将详细介绍JUnit4的关键概念、特性以及如何使用。 1. **注解驱动**: JUnit4的核心变化之一就是引入了注解,这使得测试类和方法的声明更加...

    junit4教程(《Junit4初探》)

    JUnit4是JUnit系列的第四代产品,它引入了注解(Annotations)和断言(Assertions)等新特性,使得测试代码更加简洁易读。与JUnit3相比,JUnit4的灵活性和可扩展性得到了显著提升,使得测试驱动开发(TDD)在Java...

    探索 JUnit 4.4 新特性

    随着版本的迭代,JUnit不断引入新特性和改进,以适应开发者的需求。本文将聚焦于JUnit 4.4版本,深入探讨其带来的新功能和改进。 首先,JUnit 4.4的一个显著特点是支持注解(Annotations)的增强。在早期版本中,...

    Junit4教程非常详尽

    JUnit4 是 JUnit 框架有史以来的最大改进,其主要目标便是利用 Java5 的 Annotation 特性简化测试用例的编写。下面是对 JUnit4 的详细介绍: 一、Annotation 简介 Annotation 是 Java5 中引入的一种元数据特性,...

    Junit4.zip

    JUnit4引入了许多新特性,如注解(Annotations)和参数化测试。注解使得测试类和方法的声明更加直观,例如`@Test`用于标记测试方法,`@Before`和`@After`分别用于在每个测试方法之前和之后执行初始化和清理操作。...

    Junit4简单实用

    总结来说,JUnit4 是对 JUnit3 的一个重要升级,它利用 Java 5 的注解特性极大地简化了测试用例的编写,提高了测试代码的可读性和可维护性。通过使用注解,开发者能够更自由地组织测试逻辑,同时也能够方便地扩展...

    junit3.8 和junit4 api

    JUnit 4是一个重大的更新,引入了许多新特性和改进,使得测试更加灵活和强大: 1. **测试注解(Annotations)**:JUnit 4引入了注解,如`@Test`,用于标记测试方法。此外,还有`@BeforeClass`、`@AfterClass`、`@...

    Junit4 jar包

    Junit4是由Eclipse基金会维护的一个开源项目,它是JUnit系列的第四个主要版本,相比于之前的版本,Junit4引入了许多新的特性和改进。它支持注解(Annotation-based)的测试,使得编写和组织测试代码变得更加简洁。...

    JUnit4.rar(ppt讲义)

    相比JUnit 3,JUnit 4引入了许多新特性,如注解(Annotations)、参数化测试、规则(Rules)等。注解简化了测试类的创建,例如`@Test`用于标记测试方法,`@Before`和`@After`则用于定义在每个测试方法执行前后的设置...

    Junit4所需jar包

    1. **JUnit4的特性**: - **注解驱动**:JUnit4引入了注解(如`@Test`、`@Before`、`@After`等),使测试类和方法的编写更加简洁。 - **异常断言**:测试方法抛出预期的异常时,可以使用`@Test(expected = ...

    Junit4电子教程 api

    JUnit4相比其前身JUnit3,引入了许多改进和新特性,使得测试更加灵活和强大。 1. **注解驱动测试**:JUnit4放弃了传统的继承Test类的方式,而是采用注解(@Test)来标记测试方法,使得测试类结构更加清晰,易于理解...

    Junit4教程.pdf

    Junit4是该框架的一个重大更新,它引入了许多新特性,显著地简化了测试代码的编写,使得测试更加直观和高效。本文将详细探讨JUnit4的主要改进和关键知识点。 1. **Annotation的引入**: - 在JUnit4中,核心的改变...

    junit4单元测试

    异常测试也是JUnit4的一个重要特性。你可以使用`@Test(expected = Exception.class)`注解来指定期望的异常类型,如果测试方法没有抛出该异常或者抛出了不同的异常,那么测试就会失败。 JUnit4还包括了对测试的分类...

    JUnit4使用.pdf

    #### 六、JUnit4的高级特性 - **参数化测试**:允许为同一个测试方法提供不同的数据集,以测试不同输入下的行为。 - **假设条件支持**:允许根据特定条件决定是否执行某个测试用例。 #### 七、JUnit4与开发流程的...

Global site tag (gtag.js) - Google Analytics