JUnit4快速入门(转)

JUnit4快速入门(转)
2008-08-06 10:47

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

请注意:本文主要介绍JUnit 4的最新特性和用法,并不会讲解Unit测试的基础。

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

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

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

package com.javaeedev.junit4;
public class
Math {

    
public int abs( int
value) {
        
return value >= 0 ? value : ( -
value);
     }

    
public int div( int a, int
b) {
        
return a /
b;
     }

    
/**

      * BUG: if b less than 0!
     
*/
    
public float exp( int a, int b) {
        
float r = 1
;
        
for ( int i = 0 ; i < b; i ++
)
             r
= r *
a;
        
return
r;
     }
}

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

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

public class MathTest extends TestCase {

    
public void setUp() { super
.setUp(); }
    
public void tearDown() { super
.tearDown(); }

    
public void testAbs() { assertTrue( true
); }
    
public void
testDiv() {...}
    
public void
testExp() {...}

}

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:

package com.javaeedev.junit4;

import static org.junit.Assert. *
;

import org.junit. *
;

public class
MathTest {

    
public
MathTest() {
         System.out.println(
" new MathTest instance. "
);
     }

     @Before
    
public void setUp() throws
Exception {
         System.out.println(
" call @Before before a test method "
);
     }

     @After
    
public void tearDown() throws
Exception {
         System.out.println(
" call @After after a test method "
);
     }

     @Test
    
public void
doAbs() {
         Math math
= new
Math();
         assertEquals(
200 , math.abs( 200
));
         assertEquals(
100 , math.abs( - 100
));
         assertEquals(
0 , math.abs( 0
));
     }

     @Test
    
public void
doDiv() {
         Math math
= new
Math();
         assertEquals(
5 , math.div( 100 , 20
));
         assertEquals(
4 , math.div( 100 , 21
));
     }

     @Test(expected
= ArithmeticException. class
)
    
public void
doDiv0() {
        
new Math().div( 127 , 0
);
     }

     @Test(timeout
= 1
)
    
public void
doLongTimeTask() {
        
double d = 0
;
        
for ( int i = 1 ; i < 10000000 ; i ++
)
             d
+=
i;
     }

     @Test
    
public void
testExp() {
         Math math
= new
Math();
         assertEquals(32f, math.exp(
2 , 5 ), 0.001f
);
         assertEquals(1f, math.exp(
2 , 0 ), 0.001f
);
         assertEquals(
0.5f , math.exp( 2 , ( - 1 )), 0.001f
);
     }

}

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

try {
   ...
   fail(
" No exception "
);
}
catch
(Exception e) {
  
// OK!

}

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

@Test(expected = ArithmeticException. class )
public void
doDiv0() {
    
new Math().div( 127 , 0
);
}

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

@Test(timeout = 1 )
public void
doLongTimeTask() {
    
double d = 0
;
    
for ( int i = 1 ; i < 10000000 ; i ++
)
         d
+=
i;
}

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

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

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

private static Object dbConnection;

@BeforeClass
public static void setUpBeforeClass() throws
Exception {
     System.out.println(
" call @BeforeClass and init database connection "
);
     dbConnection
= new
Object();
}

@AfterClass
public static void tearDownAfterClass() throws
Exception {
     System.out.println(
" call @AfterClass to release database connection "
);
     dbConnection
= null
;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BUG弄潮儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值