本章導(dǎo)讀
上一章介紹的Ant,主要用來(lái)構(gòu)建、包裝和發(fā)布Java程序,而Java程序的測(cè)試則由另外一個(gè)工具來(lái)完成,那就是JUnit。
本章首先對(duì)JUnit進(jìn)行介紹,闡述為什么要使用JUnit,然后介紹JUnit的下載和安裝及使用方法,最后介紹JUnit的新特性。
8.1 JUnit介紹
JUnit是一個(gè)開(kāi)源的Java單元測(cè)試框架,由 Erich Gamma 和 Kent Beck 開(kāi)發(fā)完成。
8.1.1 JUnit簡(jiǎn)介
JUnit主要用來(lái)幫助開(kāi)發(fā)人員進(jìn)行Java的單元測(cè)試,其設(shè)計(jì)非常小巧,但功能卻非常強(qiáng)大。
下面是JUnit一些特性的總結(jié):
— 提供的API可以讓開(kāi)發(fā)人員寫(xiě)出測(cè)試結(jié)果明確的可重用單元測(cè)試用例。
— 提供了多種方式來(lái)顯示測(cè)試結(jié)果,而且可以擴(kuò)展。
— 提供了單元測(cè)試批量運(yùn)行的功能,而且可以和Ant很容易地整合。
— 對(duì)不同性質(zhì)的被測(cè)對(duì)象,如Class,JSP,Servlet等,JUnit有不同的測(cè)試方法。
8.1.2 為什么要使用JUnit
以前,開(kāi)發(fā)人員寫(xiě)一個(gè)方法,如下代碼所示:
//******* AddAndSub.java**************
public Class AddAndSub {
public static int add(int m, int n) {
int num = m + n;
return num;
}
public static int sub(int m, int n) {
int num = m - n;
return num;
}
}
如果要對(duì)AddAndSub類(lèi)的add和sub方法進(jìn)行測(cè)試,通常要在main里編寫(xiě)相應(yīng)的測(cè)試方法,如下代碼所示:
//******* MathComputer.java**************
public Class AddAndSub {
public static int add(int m, int n) {
int num = m + n;
return num;
}
public static int sub(int m, int n) {
int num = m - n;
return num;
}
public static void main(String args[]) {
if (add (4, 6) == 10)) {
System.out.println(“Test Ok”);
} else {
System.out.println(“Test Fail”);
}
if (sub (6, 4) ==2)) {
System.out.println(“Test Ok”);
} else {
System.out.println(“Test Fail”);
}
}
}
從上面的測(cè)試可以看出,業(yè)務(wù)代碼和測(cè)試代碼放在一起,對(duì)于復(fù)雜的業(yè)務(wù)邏輯,一方面代碼量會(huì)非常龐大,另一方面測(cè)試代碼會(huì)顯得比較凌亂,而JUnit就能改變這樣的狀況,它提供了更好的方法來(lái)進(jìn)行單元測(cè)試。使用JUnit來(lái)測(cè)試前面代碼的示例如下:
//******* TestAddAndSub.java**************
import junit.framework.TestCase;
public Class TestAddAndSub extends TestCase {
public void testadd() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(4, 6));
}
public void testsub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(6, 4));
}
public static void main(String args[]){
junit.textui.TestRunner.run(TestAddAndSub .class); }
}
這里先不對(duì)JUnit的使用方法進(jìn)行講解,從上可以看到,測(cè)試代碼和業(yè)務(wù)代碼分離開(kāi),使得代碼比較清晰,如果將JUnit放在Eclipse中,測(cè)試起來(lái)將會(huì)更加方便。
8.2 建立JUnit的開(kāi)發(fā)環(huán)境
為了不使讀者在環(huán)節(jié)配置上浪費(fèi)太多時(shí)間,這里將一步一步地講解如何下載和配置JUnit。具體步驟如下:
8.2.1 下載JUnit
從www.junit.org可以進(jìn)入到JUnit的首頁(yè),JUnit的首頁(yè)畫(huà)面如圖8.1所示。
本書(shū)使用的版本是4.3版本,單擊“Junit4.3.zip”即可進(jìn)入下載JUnit的畫(huà)面,如圖8.2所示。
下載Junit4.3.zip,下載后解壓縮即可。
8.2.2 配置JUnit
下載Junit4.3.zip完畢,并解壓縮到D盤(pán)根目錄下后,即可開(kāi)始配置環(huán)境變量。用前面介紹的設(shè)定系統(tǒng)變量的方法,設(shè)定ClassPath,ClassPath=***;D:"junit"junit.jar,如圖8.3所示。

圖8.1 JUnit的首頁(yè)畫(huà)面

圖8.2 下載JUnit的畫(huà)面
查看是否配置好JUnit,在類(lèi)里添加如下語(yǔ)句:
import junit.framework.TestCase;

圖8.3 設(shè)定系統(tǒng)變量ClassPath
如果編譯沒(méi)有錯(cuò)誤,則說(shuō)明配置成功。
8.3 JUnit的使用方法
JUnit的使用非常簡(jiǎn)單,共有3步:第一步、編寫(xiě)測(cè)試類(lèi),使其繼承TestCase;第二步、編寫(xiě)測(cè)試方法,使用test+×××的方式來(lái)命名測(cè)試方法;第三步、編寫(xiě)斷言。如果測(cè)試方法有公用的變量等需要初始化和銷(xiāo)毀,則可以使用setUp,tearDown方法。
8.3.1 繼承TestCase
如果要使用JUnit,則測(cè)試類(lèi)都必須繼承TestCase。當(dāng)然目前的最新版JUnit是不需要繼承它的,但并不是說(shuō)TestCase類(lèi)就沒(méi)有用了,它仍然是JUnit工作的基礎(chǔ)。這里先講述繼承TestCase類(lèi)的方式,稍后再介紹不繼承的方式。
下面是前面使用JUnit進(jìn)行測(cè)試AddAndSub類(lèi)的代碼,這里進(jìn)行詳細(xì)的分析:
//******* TestAddAndSub.java**************
import junit.framework.TestCase;
public Class TestAddAndSub extends TestCase {
public void testadd() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(4, 6));
}
public void testsub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(6, 4));
}
public static void main(String args[]){
junit.textui.TestRunner.run(TestAddAndSub .class); }
}
代碼說(shuō)明:
— 這里繼承TestCase,表示該類(lèi)是一個(gè)測(cè)試類(lèi)。
— 然后使用junit.textui.TestRunner.run方法來(lái)執(zhí)行這個(gè)測(cè)試類(lèi)。
這里給出TestCase的源代碼:
//******* TestCase.java**************
package junit.framework;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public abstract class TestCase extends Assert implements Test {
/**測(cè)試案例的名稱(chēng)*/
private String fName;
/**構(gòu)造函數(shù)
*/
public TestCase() {
fName= null;
}
/**帶參數(shù)的構(gòu)造函數(shù)
*/
public TestCase(String name) {
fName= name;
}
/**獲取被run執(zhí)行的測(cè)試案例的數(shù)量
*/
public int countTestCases() {
return 1;
}
/**創(chuàng)建一個(gè)TestResult
* @see TestResult
*/
protected TestResult createResult() {
return new TestResult();
}
/**執(zhí)行run方法,返回TestResult
* @see TestResult
*/
public TestResult run() {
TestResult result= createResult();
run(result);
return result;
}
/**執(zhí)行run方法,參數(shù)為T(mén)estResult
*/
public void run(TestResult result) {
result.run(this);
}
/**執(zhí)行測(cè)試方法,包括初始化和銷(xiāo)毀方法
* @throws Throwable if any exception is thrown
*/
public void runBare() throws Throwable {
Throwable exception= null;
setUp();
try {
runTest();
} catch (Throwable running) {
exception= running;
}
finally {
try {
tearDown();
} catch (Throwable tearingDown) {
if (exception == null) exception= tearingDown;
}
}
if (exception != null) throw exception;
}
/**執(zhí)行測(cè)試方法
* @throws Throwable if any exception is thrown
*/
protected void runTest() throws Throwable {
assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);
Method runMethod= null;
try {
//利用反射機(jī)制
runMethod= getClass().getMethod(fName, (Class[])null);
} catch (NoSuchMethodException e) {
fail("Method """+fName+""" not found");
}
if (!Modifier.isPublic(runMethod.getModifiers())) {
fail("Method """+fName+""" should be public");
}
//利用反射機(jī)制
try {
runMethod.invoke(this);
}
catch (InvocationTargetException e) {
e.fillInStackTrace();
throw e.getTargetException();
}
catch (IllegalAccessException e) {
e.fillInStackTrace();
throw e;
}
}
/**測(cè)試前的初始化方法
*/
protected void setUp() throws Exception {
}
/**測(cè)試后的銷(xiāo)毀方法
*/
protected void tearDown() throws Exception {
}
/**返回測(cè)試案例的名稱(chēng)
* @return the name of the TestCase
*/
public String getName() {
return fName;
}
/**設(shè)定測(cè)試案例的名稱(chēng)
* @param name the name to set
*/
public void setName(String name) {
fName= name;
}
}
代碼說(shuō)明:
— 該類(lèi)繼承了Assert 類(lèi),實(shí)現(xiàn)了Test接口。
— 可以看出,TestCase類(lèi)正是通過(guò)runBare實(shí)現(xiàn)了在測(cè)試方法前初始化相關(guān)變量和環(huán)境,在測(cè)試方法后銷(xiāo)毀相關(guān)變量和環(huán)境。
8.3.2 編寫(xiě)測(cè)試方法
測(cè)試方法名要以test+方法名來(lái)命名,當(dāng)然最新版的JUnit支持直接以方法名來(lái)命名測(cè)試方法。這是通過(guò)TestCase類(lèi)里的runTest方法來(lái)實(shí)現(xiàn)的,主要利用了Java的反射機(jī)制,runTest方法的代碼如下:
protected void runTest() throws Throwable {
assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);
Method runMethod= null;
try {
// 獲取要測(cè)試的方法
runMethod= getClass().getMethod(fName, (Class[])null);
} catch (NoSuchMethodException e) {
fail("Method """+fName+""" not found");
}
//判斷要測(cè)試的方法是否為公用方法
if (!Modifier.isPublic(runMethod.getModifiers())) {
fail("Method """+fName+""" should be public");
}
//Java的反射機(jī)制
try {
runMethod.invoke(this);
}
//拋出調(diào)用異常
catch (InvocationTargetException e) {
e.fillInStackTrace();
throw e.getTargetException();
}
catch (IllegalAccessException e) {
e.fillInStackTrace();
throw e;
}
}
8.3.3 編寫(xiě)斷言
JUnit主要有以下斷言:
— assertEquals(期望值,實(shí)際值),檢查兩個(gè)值是否相等。
— assertEquals(期望對(duì)象,實(shí)際對(duì)象),檢查兩個(gè)對(duì)象是否相等,利用對(duì)象的equals()方法進(jìn)行判斷。
— assertSame(期望對(duì)象,實(shí)際對(duì)象),檢查具有相同內(nèi)存地址的兩個(gè)對(duì)象是否相等,利用內(nèi)存地址進(jìn)行判斷,注意和上面assertEquals方法的區(qū)別。
— assertNotSame(期望對(duì)象,實(shí)際對(duì)象),檢查兩個(gè)對(duì)象是否不相等。
— assertNull(對(duì)象1,對(duì)象2),檢查一個(gè)對(duì)象是否為空。
— assertNotNull(對(duì)象1,對(duì)象2),檢查一個(gè)對(duì)象是否不為空。
— assertTrue(布爾條件),檢查布爾條件是否為真。
— assertFalse(布爾條件),檢查布爾條件是否為假。
這些斷言主要定義在JUnit的Assert類(lèi)里,Assert類(lèi)的示例代碼如下:
//******* Assert.java**************
package junit.framework;
/**一系列的斷言方法
*/
public class Assert {
/**構(gòu)造函數(shù)
*/
protected Assert() {
}
/**斷言是否為真,帶消息
*/
static public void assertTrue(String message, boolean condition) {
if (!condition)
fail(message);
}
/**斷言是否為真
*/
static public void assertTrue(boolean condition) {
assertTrue(null, condition);
}
/**斷言是否為假,帶消息
*/
static public void assertFalse(String message, boolean condition) {
assertTrue(message, !condition);
}
/**斷言是否為假
*/
static public void assertFalse(boolean condition) {
assertFalse(null, condition);
}
/**斷言是否為失敗
*/
static public void fail(String message) {
throw new AssertionFailedError(message);
}
/**斷言是否為失敗
*/
static public void fail() {
fail(null);
}
/**是否相等的斷言,帶消息Object
*/
static public void assertEquals(String message, Object expected, Object actual) {
if (expected == null && actual == null)
return;
if (expected != null && expected.equals(actual))
return;
failNotEquals(message, expected, actual);
}
/**是否相等的斷言,Object
*/
static public void assertEquals(Object expected, Object actual) {
assertEquals(null, expected, actual);
}
/**是否相等的斷言,帶消息String
*/
static public void assertEquals(String message, String expected, String actual) {
if (expected == null && actual == null)
return;
if (expected != null && expected.equals(actual))
return;
throw new ComparisonFailure(message, expected, actual);
}
/**是否相等的斷言,String
*/
static public void assertEquals(String expected, String actual) {
assertEquals(null, expected, actual);
}
/**是否相等的斷言,帶消息double
*/
static public void assertEquals(String message, double expected, double actual, double delta) {
if (Double.compare(expected, actual) == 0)
return;
if (!(Math.abs(expected-actual) <= delta))
failNotEquals(message, new Double(expected), new Double(actual));
}
/**是否相等的斷言,double
*/
static public void assertEquals(double expected, double actual, double delta) {
assertEquals(null, expected, actual, delta);
}
/**是否相等的斷言,帶消息float
*/
static public void assertEquals(String message, float expected, float actual, float delta) {
if (Float.compare(expected, actual) == 0)
return;
if (!(Math.abs(expected - actual) <= delta))
failNotEquals(message, new Float(expected), new Float(actual));
}
/**是否相等的斷言, float
*/
static public void assertEquals(float expected, float actual, float delta) {
assertEquals(null, expected, actual, delta);
}
/**是否相等的斷言,帶消息long
*/
static public void assertEquals(String message, long expected, long actual) {
assertEquals(message, new Long(expected), new Long(actual));
}
/**是否相等的斷言, long
*/
static public void assertEquals(long expected, long actual) {
assertEquals(null, expected, actual);
}
/**是否相等的斷言,帶消息boolean
*/
static public void assertEquals(String message, boolean expected, boolean actual) {
assertEquals(message, Boolean.valueOf(expected), Boolean.valueOf(actual));
}
/**是否相等的斷言,boolean
*/
static public void assertEquals(boolean expected, boolean actual) {
assertEquals(null, expected, actual);
}
/**是否相等的斷言,帶消息byte
*/
static public void assertEquals(String message, byte expected, byte actual) {
assertEquals(message, new Byte(expected), new Byte(actual));
}
/**是否相等的斷言, byte
*/
static public void assertEquals(byte expected, byte actual) {
assertEquals(null, expected, actual);
}
/**是否相等的斷言,帶消息char
*/
static public void assertEquals(String message, char expected, char actual) {
assertEquals(message, new Character(expected), new Character(actual));
}
/**是否相等的斷言,char
*/
static public void assertEquals(char expected, char actual) {
assertEquals(null, expected, actual);
}
/**是否相等的斷言,帶消息short
*/
static public void assertEquals(String message, short expected, short actual) {
assertEquals(message, new Short(expected), new Short(actual));
}
/**是否相等的斷言,short
static public void assertEquals(short expected, short actual) {
assertEquals(null, expected, actual);
}
/**是否相等的斷言,帶消息int
*/
static public void assertEquals(String message, int expected, int actual) {
assertEquals(message, new Integer(expected), new Integer(actual));
}
/**是否相等的斷言,int
*/
static public void assertEquals(int expected, int actual) {
assertEquals(null, expected, actual);
}
/**是否不為null的斷言 Object
*/
static public void assertNotNull(Object object) {
assertNotNull(null, object);
}
/**是否不為null的斷言,帶消息Object
*/
static public void assertNotNull(String message, Object object) {
assertTrue(message, object != null);
}
/**是否為null的斷言O(shè)bject
*/
static public void assertNull(Object object) {
assertNull(null, object);
}
/**是否為null的斷言,帶消息Object
*/
static public void assertNull(String message, Object object) {
assertTrue(message, object == null);
}
/**是否相同的斷言,帶消息*/
static public void assertSame(String message, Object expected, Object actual) {
if (expected == actual)
return;
failNotSame(message, expected, actual);
}
/**是否相同的斷言,Object
*/
static public void assertSame(Object expected, Object actual) {
assertSame(null, expected, actual);
}
/**是否不相同的斷言,帶消息
*/
static public void assertNotSame(String message, Object expected, Object actual) {
if (expected == actual)
failSame(message);
}
/**是否不相同的斷言O(shè)bject
*/
static public void assertNotSame(Object expected, Object actual) {
assertNotSame(null, expected, actual);
}
/**相同時(shí)失敗
*/
static public void failSame(String message) {
String formatted= "";
if (message != null)
formatted= message+" ";
fail(formatted+"expected not same");
}
/**不相同時(shí)失敗
*/
static public void failNotSame(String message, Object expected, Object actual) {
String formatted= "";
if (message != null)
formatted= message+" ";
fail(formatted+"expected same:<"+expected+"> was not:<"+actual+">");
}
/**不相等時(shí)失敗
*/
static public void failNotEquals(String message, Object expected, Object actual) {
fail(format(message, expected, actual));
}
/**格式化消息
*/
public static String format(String message, Object expected, Object actual) {
String formatted= "";
if (message != null)
formatted= message+" ";
return formatted+"expected:<"+expected+"> but was:<"+actual+">";
}
}
從上述代碼中,讀者可以研讀JUnit中有關(guān)斷言的實(shí)現(xiàn)方式,其實(shí),最終都是使用后面的幾個(gè)static方法來(lái)實(shí)現(xiàn)的。
8.4 JUnit的新特性
Java 5的發(fā)布為JUnit帶來(lái)了新的特性。自JUnit 4.0之后,JUnit大量使用了annotations特性,使編寫(xiě)單元測(cè)試變得更加簡(jiǎn)單。
8.4.1 改變測(cè)試方法的命名方式
前面講過(guò),使用JUnit 4.0以上版本可以不用遵循以前JUnit約定的測(cè)試方法命名方法,以前命名方法的示例代碼如下:
//******* TestAddAndSub.java**************
import junit.framework.TestCase;
public class TestAddAndSub extends TestCase {
public void testadd() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(4, 6));
}
public void testsub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(6, 4));
}
public static void main(String args[]){
junit.textui.TestRunner.run(TestAddAndSub .class); }
}
JUnit 4.0以上版本的命名方式,是在測(cè)試方法前使用@Test注釋?zhuān)纠a如下:
//******* TestAddAndSub.java**************
import junit.framework.TestCase;
import org.junit.*;
public class TestAddAndSub extends TestCase {
@Test public void add() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(4, 6));
}
@Test public void sub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(6, 4));
}
}
這個(gè)時(shí)候,測(cè)試方法的命名將不再重要,開(kāi)發(fā)人員可以按照自己的命名方式來(lái)命名。
8.4.2 不再繼承TestCase
新版本的JUnit將不再?gòu)?qiáng)制繼承TestCase,但需要import org.junit.Assert來(lái)實(shí)現(xiàn)斷言,示例代碼如下:
//******* TestAddAndSub.java**************
import static org.junit.Assert.assertEquals;
import org.junit.*;
public class TestAddAndSub{
@Test public void add() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(4, 6));
}
@Test public void sub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(6, 4));
}
}
8.4.3 改變初始化和銷(xiāo)毀方式
以前,JUnit使用SetUp和TearDown方法來(lái)進(jìn)行初始化和銷(xiāo)毀動(dòng)作,JUnit 4.0以上版本將不再?gòu)?qiáng)制使用SetUp和TearDown方法來(lái)進(jìn)行初始化和銷(xiāo)毀,原來(lái)使用SetUp和TearDown方法的示例代碼如下:
//******* TestAddAndSub.java**************
import junit.framework.TestCase;
public class TestAddAndSub extends TestCase {
private int m = 0;
private int n = 0;
//初始化
protected void setUp() {
m = 4;
n = 6;
}
public void testadd() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(m, n));
}
public void testsub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(n, m));
}
//銷(xiāo)毀
protected void tearDown() {
m = 0;
n = 0;
}
}
不使用SetUp和TearDown方法的示例代碼如下:
//******* TestAddAndSub.java**************
import static org.junit.Assert.assertEquals;
import org.junit.*;
public class TestAddAndSub {
protected int m = 0;
protected int n = 0;
//初始化
@Before public void init() {
m = 4;
n = 6;
}
@Test public void add() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(m, n));
}
@Test public void sub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(n, m));
}
//銷(xiāo)毀
@After public void destory() {
m = 0;
n = 0;
}
}
上面示例中的初始化和銷(xiāo)毀都是針對(duì)一個(gè)方法來(lái)說(shuō)的,每個(gè)方法執(zhí)行前都要進(jìn)行初始化,執(zhí)行完畢都要進(jìn)行銷(xiāo)毀。而JUnit的最新版本則提供了新的特性,針對(duì)類(lèi)進(jìn)行初始化和銷(xiāo)毀。也就是說(shuō),該類(lèi)中的方法只進(jìn)行一次初始化和銷(xiāo)毀,方法就是使用@Before和@After,示例代碼如下:
//******* TestAddAndSub.java**************
import static org.junit.Assert.assertEquals;
import org.junit.*;
public class TestAddAndSub {
protected int m = 0;
protected int n = 0;
//初始化
@BeforeClass public void init() {
m = 4;
n = 6;
}
@Test public void add() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(m, n));
}
@Test public void sub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(n, m));
}
//銷(xiāo)毀
@AfterClass public void destory() {
m = 0;
n = 0;
}
}
上述初始化和銷(xiāo)毀動(dòng)作,只執(zhí)行一次即可。
8.4.4 改變異常處理的方式
以前,使用JUnit進(jìn)行單元測(cè)試時(shí),如果遇到異常情況,需要使用try…catch的形式來(lái)捕捉異常,示例代碼如下:
//******* TestAddAndSub.java**************
import junit.framework.TestCase;
public class TestAddAndSub extends TestCase {
private int m = 0;
private int n = 0;
//初始化
protected void setUp() {
m = 4;
n = 6;
}
public void testadd() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(m, n));
}
public void testsub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(n, m));
}
public void testdiv() {
//斷言除數(shù)為0
try {
int n = 2 / 0;
fail("Divided by zero!");
}
catch (ArithmeticException success) {
assertNotNull(success.getMessage());
}
}
//銷(xiāo)毀
protected void tearDown() {
m = 0;
n = 0;
}
}
JUnit4.0以后的版本將不再使用try…catch的方式來(lái)捕捉異常,示例代碼如下:
//******* TestAddAndSub.java**************
import static org.junit.Assert.assertEquals;
import org.junit.*;
public class TestAddAndSub {
protected int m = 0;
protected int n = 0;
//初始化
@Before public void init() {
m = 4;
n = 6;
}
@Test public void add() {
//斷言計(jì)算結(jié)果與10是否相等
assertEquals(10, AddAndSub.add(m, n));
}
@Test public void sub() {
//斷言計(jì)算結(jié)果與2是否相等
assertEquals(2, AddAndSub.sub(n, m));
}
@Test t(expected=ArithmeticException.class) public void div() {
//斷言除數(shù)是否為0
int n = 2 / 0;
}
//銷(xiāo)毀
@After public void destory() {
m = 0;
n = 0;
}
}
當(dāng)然,JUnit還有許多新的特性,限于篇幅原因,這里只對(duì)比較重要的特性進(jìn)行講解,其余將不再多講,想要了解的讀者可以到JUnit的相關(guān)網(wǎng)站進(jìn)行學(xué)習(xí)。
8.5 小結(jié)
本章首先講述了JUnit的下載和安裝,接著又講解了JUnit的相關(guān)知識(shí),最后講解了JUnit的新特性。
JUnit對(duì)開(kāi)發(fā)人員進(jìn)行大規(guī)模的單元測(cè)試來(lái)說(shuō),是非常有用的,但對(duì)于大量的代碼如何來(lái)管理就只有靠CVS了。CVS是一個(gè)版本控制系統(tǒng),主要用來(lái)管理開(kāi)發(fā)人員代碼的歷史,下一章主要講如何使用CVS。