简要说JUnit的4大功能 
1. 管理测试用例。修改了哪些代码,这些代码的修改会对哪些部分有影响,通过JUnit将这次的修改做个完整测试。这也就JUnit中所谓的TestSuite。 
2. 定义测试代码。这也就是JUnit中所谓的TestCase,根据源代码的测试需要定义每个TestCase,并将TestCase添加到相应的TestSuite方便管理。 
3. 定义测试环境。在TestCase测试前会先调用“环境”配置,在测试中使用,当然也可以在测试用例中直接定义测试环境。 
4. 检测测试结果。对于每种正常、异常情况下的测试,运行结果是什么、结果是否是我们预期的等都需要有个明确的定义,JUnit在这方面提供了强大的功能。

      以上部分与我们平常使用IDE调试的过程是完全一样的,只不过是增加了测试用例管理、测试结果检测等功能,提高了单元的效率,保证了单元测试的完整性,明确了单元测试的目标。

一、测试用例:

1 package can.test;    
 2 
 3 import java.util.ArrayList;    
 4 import java.util.Collection;    
 5 import junit.framework.TestCase;    
 6 
 7 public class SampleTest extends TestCase {    
 8 
 9         protected void setUp() {    
10                 /* 开始test前的准备操作:初始化,获取数据连接... */    
11                                  
12         }    
13                     
14         protected void tearDown() {    
15                 /* 完成test后的清理工作:关闭文件, 关闭数据连接... */    
16                                     
17         }    
18                     
19         public void testEmpty() {    
20                 /* test case 1*/    
21                 Collection collection = new ArrarList();    
22                 assertTrue(collection.isEmpty());    
23         }    
24                     
25         public void testCase2() {    
26                 /* test case 2*/    
27                 ArrayList emptyList = new ArrayList(); 
28                 try { 
29                         Object o = emptyList.get(0); 
30                         fail("Should raise an IndexOutOfBoundsException"); 
31                 } catch (IndexOutOfBoundsException expected) { 
32                         assertTrue(true); 
33                 } 
34         }    
35 }

1. 当需要进行test前后操作,则对setUp(), tearDown()这两个方法进行重写。

 

2. 每进行一个test case前后,都会调用setUp(), tearDown()。注意,不是一次调用setUp(), 然后进行多个test case,最后才调用tearDown()。而且选择test case的次序是不确定的。所以调用次序可能是:
     1  setUp()
     2  testYYY()
     3  tearDown()
     4  setUp()
     5  testXXX()
     6  tearDown()
     所以每个testcase不要存在数据上的前后联系。

 

3. 编译&运行

compile:  javac  -cp ../lib/junit.jar  can/junit/ SampleTest.java
    run:  (文本界面)   java  -cp   .;../lib/junit.jar  junit.textui.TestRunner  can.junit.SampleTest
      (图形界面)    java  -cp   .;../lib/junit.jar  junit.swingui.TestRunner  can.junit.SampleTest

 

.表示把当前目录添加到classpath,便于junit能够在该目录找到can.junit.SampleTest

 

4. 加上main(可选)

    如果你觉得每次都要在命令中指定文本界面或图形界面,有点麻烦,那可以添加一下代码到SampleTest类中:

import junit.framework.Test; 
import junit.framework.TestSuite; 


        public static Test suite() { 
                /* 添加SampleTest类到TestSuite*/ 
                return new TestSuite(SampleTest.class); 
        } 

        public static void main(String args[]) { 
                /* 指定文本界面*/ 
                junit.textui.TestRunner.run(suite()); 
        }

或者

public static void main(String args[]) { 
                junit.textui.TestRunner.run(SampleTest.class); 
        }

 这样run: java  -cp  .;../lib/junit.jar    can.junit. SampleTest

 

二. 测试单元

      当需要对多个类或者模块进行unit test的时候,我们都会写好每个类的testcase,然后写一个Suite来将它们串联起来。

1 package can.junit; 
 2 
 3 import junit.framework.Test; 
 4 import junit.framework.TestSuite; 
 5 
 6 public class SampleTestSuite { 
 7 
 8         public static Test suite() { 
 9                 TestSuite suite = new TestSuite("Sample Tests"); 
10                  
11                 /* 逐一添加testCase类 */ 
12                 suite.addTestSuite(SampleTest.class); 
13                  
14                 /* 逐一添加test suite(注意,这是递归调用的) */ 
15                 suite.addTest(AnotherTestSuite.suite()); 
16 
17                 return suite; 
18         } 
19 
20         public static void main(String args[]) { 
21                 junit.textui.TestRunner.run(suite()); 
22         } 
23 }

刚才说了,每进行一个test case,setUp()和tearDown()都会调用。而有的时候,在setUp()中相当耗费资源,我们想进行所有的test case仅调用一次setUp()和tearDown(),这样需要把TestSuite包装到TestSetup类中:

1 import junit.framework.*;    
 2 import junit.extensions.TestSetup;    
 3 
 4 public class AllTestsOneTimeSetup {    
 5 
 6         public static Test suite() {    
 7             
 8                 TestSuite suite = new TestSuite();    
 9                 suite.addTest(SomeTest.suite());    
10                 suite.addTest(AnotherTest.suite());    
11 
12                 TestSetup wrapper = new TestSetup(suite) {    
13                         protected void setUp() {    
14                                 oneTimeSetUp();    
15                         }    
16 
17                         protected void tearDown() {    
18                                 oneTimeTearDown();    
19                         }    
20                 };    
21                 return wrapper;    
22         }    
23 
24         public static void oneTimeSetUp() {    
25                 // one-time initialization code    
26         }    
27 
28         public static void oneTimeTearDown() {    
29                 // one-time cleanup code    
30         }         
31 }

三. 其他

对于protected方法的test,可以把test case放在被test的类同一目录。