日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JUnit4用法详解

發(fā)布時間:2025/6/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JUnit4用法详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

淺談TDD

測試驅(qū)動開發(fā),它是敏捷開發(fā)的最重要的部分。方法主要是先根據(jù)客戶的需求編寫測試程序,然后再編碼使其通過測試。在敏捷開發(fā)實施中,開發(fā)人員主要從兩個方面去理解測試驅(qū)動開發(fā)。

a)在測試的輔助下,快速實現(xiàn)客戶需求的功能。通過編寫測試用例,對客戶需求的功能進行分解,并進行系統(tǒng)設計。我們發(fā)現(xiàn)從使用角度對代碼的設計通常更符合后期開發(fā)的需求??蓽y試的要求,對代碼的內(nèi)聚性的提高和復用都非常有益。?
b)在測試的保護下,不斷重構(gòu)代碼,提高代碼的重用性,從而提高軟件產(chǎn)品的質(zhì)量??梢姕y試驅(qū)動開發(fā)實施的好壞確實極大的影響軟件產(chǎn)品的質(zhì)量,貫穿了軟件開發(fā)的始終。?
在測試驅(qū)動開發(fā)中,為了保證測試的穩(wěn)定性,被測代碼接口的穩(wěn)定性是非常重要的。否則,變化的成本就會急劇的上升。所以,自動化測試將會要求您的設計依賴于接口,而不是具體的類。進而推動設計人員重視接口的設計,體現(xiàn)系統(tǒng)的可擴展性和抗變性。?


JUnit4的用法介紹

Java 語言現(xiàn)在支持泛型、枚舉、可變長度參數(shù)列表和注釋,這些特性為可重用的框架設計帶來了新的可能。
JUnit4利用 Java 5 的新特性(尤其是注釋)的優(yōu)勢,使得單元測試比起用最初的 JUnit 來說更加簡單。?

測試方法 @Test

以前所有版本的 JUnit 都使用命名約定和反射來定位測試。例如,下面的代碼測試 1 + 1 等于 2:

?

import?junit.framework.TestCase;
public?class?AdditionTest?extends?TestCase?{
private?int?x?=?1;
private?int?y?=?1;
public?void?testAddition()?{
int?z?=?x?+?y;
assertEquals(2,?z);
}

}


而在 JUnit4 中,測試是由 @Test 注釋來識別的,如下所示:

import?org.junit.Test;import?junit.framework.TestCase;public?class?AdditionTest?{private?int?x?=?1;private?int?y?=?1;@Testpublic?void?testAddition()?{int?z?=?x?+?y;assertEquals(2,?z);}}

使用注釋來識別測試方法的優(yōu)點是不再需要將所有的方法命名為 testAddition()、testXXX()的形式等等。
例如,下面的方法也可以工作:

import?org.junit.Test;import?junit.framework.TestCase;public?class?AdditionTest?{private?int?x?=?1;private?int?y?=?1;@Testpublic?void?addition()?{int?z?=?x?+?y;assertEquals(2,?z);}}

使用這種方法的好處是:
a)允許我們遵循最適合的應用程序的命名約定。
我們可以將測試方法使用與被測試的類相同的名稱(由開發(fā)組規(guī)范約定)。例如,LoginAction.login() 由 LoginActionTest.login()方法測試、LoginAction.check()由LoginActionTest.check()方法測試等等。
b)使用JUnit4后,測試用例類可以不繼承TestCase類,所以我們也就可以擴展被測試類了。
這種方法使得測試受保護的方法非常容易,我們只要將測試用例類繼承被測試類,就可以測試受保護方法了。?

@Before(SetUp)

JUnit 3 測試運行程序會在運行每個測試之前自動調(diào)用 setUp() 方法。該方法一般會初始化字段、準備數(shù)據(jù)等等。例如下面的 setUp() 方法,用于設定要加載的路由文件:

?

public?void?setUp()?{
//?加載此測試用例的servicerouting配置文件
ServiceRouting.loadConfig("com/demo/servicerouting.conf");
//?
}



在 JUnit4 中,我們?nèi)匀豢梢栽诿總€測試方法運行之前初始化字段或準備數(shù)據(jù)。然而,完成這些操作的方法不再需要叫做 setUp(),只要用 @Before 注釋來指示該方法即可,如下所示:

?

@Before
public?void?initialize()?{
//?加載此測試用例的servicerouting配置文件
ServiceRouting.loadConfig("com/demo/servicerouting.conf");
//?
}



JUnit4允許我們使用 @Before 來注釋多個方法,這些方法都在每個測試之前運行:

?

@Before
public?void?initialize()?{
//?加載此測試用例的servicerouting配置文件
ServiceRouting.loadConfig("com/demo/servicerouting.conf");
//?
}

@Before
public?void?prepareRetData()?{
//
}



@After(TearDown)

清除方法與初始化方法類似。在 JUnit3 中,我們要將方法命名為 tearDown() 才可以實現(xiàn)清除方法,但在JUnit4中,只要給方法添加@After標注即可。
例如:

?

????@After
public?static?void?clearContext()?{
ActionContext.getContext().put(StrutsStatics.HTTP_REQUEST,?null);
ActionContext.setContext(null);
}



測試方法結(jié)束后清除為此測試用例準備的一些數(shù)據(jù)。
與 @Before 一樣,也可以用 @After 來注釋多個清除方法,這些方法都在每個測試之后運行。?
最后,我們不再需要顯式調(diào)用在超類中的初始化和清除方法,只要它們不被覆蓋,測試運行程序?qū)⒏鶕?jù)需要自動為您調(diào)用這些方法。
超類中的 @Before 方法在子類中的 @Before 方法之前被調(diào)用(這反映了構(gòu)造函數(shù)調(diào)用的順序)。
@After 方法以反方向運行:子類中的方法在超類中的方法之前被調(diào)用。否則,多個 @Before 或 @After 方法的相對順序就得不到保證。


@Before和@After小結(jié)

假設測試類中有如下方法定義:

?

@Before
public?void?init(){}
@After
public?void?destroy(){}

則Before、After方法的執(zhí)行流程如圖所示:

淺談TDD

測試驅(qū)動開發(fā),它是敏捷開發(fā)的最重要的部分。方法主要是先根據(jù)客戶的需求編寫測試程序,然后再編碼使其通過測試。在敏捷開發(fā)實施中,開發(fā)人員主要從兩個方面去理解測試驅(qū)動開發(fā)。

a)在測試的輔助下,快速實現(xiàn)客戶需求的功能。通過編寫測試用例,對客戶需求的功能進行分解,并進行系統(tǒng)設計。我們發(fā)現(xiàn)從使用角度對代碼的設計通常更符合后期開發(fā)的需求。可測試的要求,對代碼的內(nèi)聚性的提高和復用都非常有益。?
b)在測試的保護下,不斷重構(gòu)代碼,提高代碼的重用性,從而提高軟件產(chǎn)品的質(zhì)量??梢姕y試驅(qū)動開發(fā)實施的好壞確實極大的影響軟件產(chǎn)品的質(zhì)量,貫穿了軟件開發(fā)的始終。?
在測試驅(qū)動開發(fā)中,為了保證測試的穩(wěn)定性,被測代碼接口的穩(wěn)定性是非常重要的。否則,變化的成本就會急劇的上升。所以,自動化測試將會要求您的設計依賴于接口,而不是具體的類。進而推動設計人員重視接口的設計,體現(xiàn)系統(tǒng)的可擴展性和抗變性。?


JUnit4的用法介紹

Java 語言現(xiàn)在支持泛型、枚舉、可變長度參數(shù)列表和注釋,這些特性為可重用的框架設計帶來了新的可能。
JUnit4利用 Java 5 的新特性(尤其是注釋)的優(yōu)勢,使得單元測試比起用最初的 JUnit 來說更加簡單。?

測試方法 @Test

以前所有版本的 JUnit 都使用命名約定和反射來定位測試。例如,下面的代碼測試 1 + 1 等于 2:

?

import?junit.framework.TestCase;
public?class?AdditionTest?extends?TestCase?{
private?int?x?=?1;
private?int?y?=?1;
public?void?testAddition()?{
int?z?=?x?+?y;
assertEquals(2,?z);
}

}


而在 JUnit4 中,測試是由 @Test 注釋來識別的,如下所示:

?

import?org.junit.Test;
import?junit.framework.TestCase;
public?class?AdditionTest?{
private?int?x?=?1;
private?int?y?=?1;
@Test
public?void?testAddition()?{
int?z?=?x?+?y;
assertEquals(2,?z);
}

}


使用注釋來識別測試方法的優(yōu)點是不再需要將所有的方法命名為 testAddition()、testXXX()的形式等等。
例如,下面的方法也可以工作:

?

import?org.junit.Test;
import?junit.framework.TestCase;
public?class?AdditionTest?{
private?int?x?=?1;
private?int?y?=?1;
@Test
public?void?addition()?{
int?z?=?x?+?y;
assertEquals(2,?z);
}

}


使用這種方法的好處是:
a)允許我們遵循最適合的應用程序的命名約定。
我們可以將測試方法使用與被測試的類相同的名稱(由開發(fā)組規(guī)范約定)。例如,LoginAction.login() 由 LoginActionTest.login()方法測試、LoginAction.check()由LoginActionTest.check()方法測試等等。
b)使用JUnit4后,測試用例類可以不繼承TestCase類,所以我們也就可以擴展被測試類了。
這種方法使得測試受保護的方法非常容易,我們只要將測試用例類繼承被測試類,就可以測試受保護方法了。?

@Before(SetUp)

JUnit 3 測試運行程序會在運行每個測試之前自動調(diào)用 setUp() 方法。該方法一般會初始化字段、準備數(shù)據(jù)等等。例如下面的 setUp() 方法,用于設定要加載的路由文件:

?

public?void?setUp()?{
//?加載此測試用例的servicerouting配置文件
ServiceRouting.loadConfig("com/demo/servicerouting.conf");
//?
}


在 JUnit4 中,我們?nèi)匀豢梢栽诿總€測試方法運行之前初始化字段或準備數(shù)據(jù)。然而,完成這些操作的方法不再需要叫做 setUp(),只要用 @Before 注釋來指示該方法即可,如下所示:

?

@Before
public?void?initialize()?{
//?加載此測試用例的servicerouting配置文件
ServiceRouting.loadConfig("com/demo/servicerouting.conf");
//?
}


JUnit4允許我們使用 @Before 來注釋多個方法,這些方法都在每個測試之前運行:

?

@Before
public?void?initialize()?{
//?加載此測試用例的servicerouting配置文件
ServiceRouting.loadConfig("com/demo/servicerouting.conf");
//?
}

@Before
public?void?prepareRetData()?{
//
}



@After(TearDown)

清除方法與初始化方法類似。在 JUnit3 中,我們要將方法命名為 tearDown() 才可以實現(xiàn)清除方法,但在JUnit4中,只要給方法添加@After標注即可。
例如:?

???@After
public?static?void?clearContext()?{
ActionContext.getContext().put(StrutsStatics.HTTP_REQUEST,?null);
ActionContext.setContext(null);
}


測試方法結(jié)束后清除為此測試用例準備的一些數(shù)據(jù)。
與 @Before 一樣,也可以用 @After 來注釋多個清除方法,這些方法都在每個測試之后運行。?
最后,我們不再需要顯式調(diào)用在超類中的初始化和清除方法,只要它們不被覆蓋,測試運行程序?qū)⒏鶕?jù)需要自動為您調(diào)用這些方法。
超類中的 @Before 方法在子類中的 @Before 方法之前被調(diào)用(這反映了構(gòu)造函數(shù)調(diào)用的順序)。
@After 方法以反方向運行:子類中的方法在超類中的方法之前被調(diào)用。否則,多個 @Before 或 @After 方法的相對順序就得不到保證。


@Before和@After小結(jié)

假設測試類中有如下方法定義:

?

@Before
public?void?init(){}
@After
public?void?destroy(){}

則Before、After方法的執(zhí)行流程如圖所示:


這種方法有明顯的缺陷,如果要初始化的是數(shù)據(jù)庫的鏈接,或者是一個大的對象的話,而這些資源恰恰是整個測試用例類可以共用的,每次都去申請,確實是種浪費。所以JUnit4引入了@BeforeClass和@AfterClass。


@BeforeClass和@AfterClass

JUnit4 也引入了一個 JUnit3 中沒有的新特性:類范圍的 setUp() 和 tearDown() 方法。任何用 @BeforeClass 注釋的方法都將在該類中的測試方法運行之前剛好運行一次,而任何用 @AfterClass 注釋的方法都將在該類中的所有測試都運行之后剛好運行一次。
例如,假設類中的每個測試都使用一個數(shù)據(jù)庫連接、一個非常大的數(shù)據(jù)結(jié)構(gòu),或者申請其他一些資源。不要在每個測試之前都重新創(chuàng)建它,您可以創(chuàng)建它一次,用完后將其銷毀清除。該方法將使得有些測試案例運行起來快得多。
注意:被注釋為 BeforeClass和AfterClass 的方法必須為static方法。?
用法如下:

????@BeforeClasspublic?static?void?classInit()?{Map?callRet?=?new?HashMap();List<ErrorCodeMessageBean>?list?=?new?ArrayList<ErrorCodeMessageBean>();list.add(createMsgBean("TDE0001",?"第一個錯誤消息"));list.add(createMsgBean("TDP9999",?"格式化{0}{1}"));list.add(createMsgBean("TDE1000~TDF0001",?"區(qū)間錯誤消息"));list.add(createMsgBean("TDG0001~",?"有下限的區(qū)間錯誤消息"));list.add(createMsgBean("~TDD0001",?"有上限的區(qū)間錯誤消息"));list.add(createMsgBean("~",?"默認的消息"));callRet.put(ErrorCodeMessageBean.codeMsgBeanKey,?list);ServiceCall.expectLastCallReturn(callRet);}@Testpublic?void?oneTestMethod()?{//.}@AfterClasspublic?static?void?classDestroy()?{ServiceCall.expectLastCallReturn(null);}

這個特定雖然很好,但是一定要小心對待這個特性。它有可能會違反測試的獨立性,并引入非預期的混亂。如果一個測試在某種程度上改變了 @BeforeClass 所初始化的一個對象,那么它有可能會影響其他測試的結(jié)果。也就是說,由BeforeClass申請或創(chuàng)建的資源,如果是整個測試用例類共享的,那么盡量不要讓其中任何一個測試方法改變那些共享的資源,這樣可能對其他測試方法有影響。它有可能在測試套件中引入順序依賴,并隱藏 bug。

BeforeClass和AfterClass的執(zhí)行流程如下:

這種方法有明顯的缺陷,如果要初始化的是數(shù)據(jù)庫的鏈接,或者是一個大的對象的話,而這些資源恰恰是整個測試用例類可以共用的,每次都去申請,確實是種浪費。所以JUnit4引入了@BeforeClass和@AfterClass。


@BeforeClass和@AfterClass

JUnit4 也引入了一個 JUnit3 中沒有的新特性:類范圍的 setUp() 和 tearDown() 方法。任何用 @BeforeClass 注釋的方法都將在該類中的測試方法運行之前剛好運行一次,而任何用 @AfterClass 注釋的方法都將在該類中的所有測試都運行之后剛好運行一次。
例如,假設類中的每個測試都使用一個數(shù)據(jù)庫連接、一個非常大的數(shù)據(jù)結(jié)構(gòu),或者申請其他一些資源。不要在每個測試之前都重新創(chuàng)建它,您可以創(chuàng)建它一次,用完后將其銷毀清除。該方法將使得有些測試案例運行起來快得多。
注意:被注釋為 BeforeClass和AfterClass 的方法必須為static方法。?
用法如下:

???@BeforeClasspublic?static?void?classInit()?{Map?callRet?=?new?HashMap();List<ErrorCodeMessageBean>?list?=?new?ArrayList<ErrorCodeMessageBean>();list.add(createMsgBean("TDE0001",?"第一個錯誤消息"));list.add(createMsgBean("TDP9999",?"格式化{0}{1}"));list.add(createMsgBean("TDE1000~TDF0001",?"區(qū)間錯誤消息"));list.add(createMsgBean("TDG0001~",?"有下限的區(qū)間錯誤消息"));list.add(createMsgBean("~TDD0001",?"有上限的區(qū)間錯誤消息"));list.add(createMsgBean("~",?"默認的消息"));callRet.put(ErrorCodeMessageBean.codeMsgBeanKey,?list);ServiceCall.expectLastCallReturn(callRet);}@Testpublic?void?oneTestMethod()?{//.}@AfterClasspublic?static?void?classDestroy()?{ServiceCall.expectLastCallReturn(null);}

這個特定雖然很好,但是一定要小心對待這個特性。它有可能會違反測試的獨立性,并引入非預期的混亂。如果一個測試在某種程度上改變了 @BeforeClass 所初始化的一個對象,那么它有可能會影響其他測試的結(jié)果。也就是說,由BeforeClass申請或創(chuàng)建的資源,如果是整個測試用例類共享的,那么盡量不要讓其中任何一個測試方法改變那些共享的資源,這樣可能對其他測試方法有影響。它有可能在測試套件中引入順序依賴,并隱藏 bug。

BeforeClass和AfterClass的執(zhí)行流程如下:




測試異常@Test(expected=XXXException.class)

異常測試是 JUnit4 中的最大改進。舊式的異常測試是在拋出異常的代碼中放入 try 塊,然后在 try 塊的末尾加入一個 fail() 語句。
例如,該方法測試被零除拋出一個 ArithmeticException:

?

public?void?testDivisionByZero()?{
try?{
int?n?=?2?/?0;
fail("Divided?by?zero!");
}

catch?(ArithmeticException?success)?{
assertNotNull(success.getMessage());
}

}


該方法不僅難看,而且寫起來也繁瑣。在 JUnit 4 中,我們現(xiàn)在可以編寫拋出異常的代碼,并使用注釋來聲明該異常是預期的:

?

????@Test(expected?=?BusinessException.class)
public?void?testExecuteNameEmpty()?throws?Exception?{
BookList?bListAction?=?new?BookList();
bListAction.setName("");
bListAction.execute();
}


附被測試代碼(如果輸入name為empty,則拋出BusinessException,若name不為"liming",則拋出MessageException異常):

????@Overridepublic?String?execute()?throws?Exception?{if?(StringUtils.isEmpty(name))?{throw?new?BusinessException("~",?"name?cant't?empty.");}if?(!StringUtils.equals("liming",?name.trim()))?{throw?new?MessageException(name?+?"?have?no?limits.");}Map?ret?=?serviceCall.call(JMockService.queryDtlInfo,?null);orderId?=?(String)?ret.get("OrderId");dataList?=?(List)?ret.get("Data");return?SUCCESS;}


參數(shù)化測試

為了保證單元測試的嚴謹性,我們經(jīng)常要模擬很多種輸入?yún)?shù),來確定我們的功能代碼是可以正常工作的,為此我們編寫大量的單元測試方法??墒沁@些測試方法都是大同小異:代碼結(jié)構(gòu)都是相同的,不同的僅僅是測試數(shù)據(jù)和期望輸出值。
JUnit4 的參數(shù)化測試方法給我們提供了更好的方法,將測試方法中相同的代碼結(jié)構(gòu)提取出來,提高代碼的重用度,減少復制粘貼代碼的痛苦。
例如下面的功能代碼(格式化字符串,將駝峰規(guī)則的字符串以"_"分隔):

?

public?class?WordDealUtil?{
public?static?String?wordFormat4DB(String?name)?{
if?(name?==?null)?{
return?null;
}

Pattern?p?=?Pattern.compile("[A-Z]");
Matcher?m?=?p.matcher(name);
StringBuffer?sb?=?new?StringBuffer();
while?(m.find())?{
if?(m.start()?!=?0)?{
m.appendReplacement(sb,?("_"?+?m.group()).toLowerCase());
}

}

return?m.appendTail(sb).toString().toLowerCase();
}

}


沒有使用參數(shù)化的測試用例代碼:

public?class?WordDealUtilTest?{/***?測試?null?時的處理情況*/@Testpublic?void?wordFormat4DBNull()?{String?target?=?null;String?result?=?WordDealUtil.wordFormat4DB(target);assertNull(result);}/***?測試空字符串的處理情況*/@Testpublic?void?wordFormat4DBEmpty()?{String?target?=?"";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("",?result);}/***?測試當首字母大寫時的情況*/@Testpublic?void?wordFormat4DBegin()?{String?target?=?"EmployeeInfo";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("employee_info",?result);}/***?測試當尾字母為大寫時的情況*/@Testpublic?void?wordFormat4DBEnd()?{String?target?=?"employeeInfoA";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("employee_info_a",?result);}/***?測試多個相連字母大寫時的情況*/@Testpublic?void?wordFormat4DBTogether()?{String?target?=?"employeeAInfo";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("employee_a_info",?result);}}

看以上測試用例代碼,結(jié)構(gòu)相似,只是輸入值與期望輸出不同而已,但我們要拷貝很多代碼。
使用參數(shù)化的測試用例代碼:

@SuppressWarnings("unchecked")@RunWith(Parameterized.class)public?class?WordDealUtilTestWithParam?{private?String?expected;private?String?target;@Parameterspublic?static?Collection?words()?{return?Arrays.asList(new?Object[][]?{{?"employee_info",?"employeeInfo"?},??//?測試一般的處理情況{?null,?null?},?????????????????????????//?測試?null?時的處理情況{?"",?""?},?????????????????????????????//?測試空字符串時的處理情況{?"employee_info",?"EmployeeInfo"?},????//?測試當首字母大寫時的情況{?"employee_info_a",?"employeeInfoA"?},?//?測試當尾字母為大寫時的情況{?"employee_a_info",?"employeeAInfo"?}??//?測試多個相連字母大寫時的情況});}/***?參數(shù)化測試必須的構(gòu)造函數(shù)*?@param?expected?????期望的測試結(jié)果,對應參數(shù)集中的第一個參數(shù)*?@param?target?????測試數(shù)據(jù),對應參數(shù)集中的第二個參數(shù)*/public?WordDealUtilTestWithParam(String?expected,?String?target)?{this.expected?=?expected;this.target?=?target;}/***?測試將?Java?對象名稱到數(shù)據(jù)庫名稱的轉(zhuǎn)換*/@Testpublic?void?wordFormat4DB()?{Assert.assertEquals(expected,?WordDealUtil.wordFormat4DB(target));}}

很明顯,代碼簡單且很清晰了。在靜態(tài)方法 words 中,我們使用二維數(shù)組來構(gòu)建測試所需要的參數(shù)列表,其中每個數(shù)組中的元素的放置順序并沒有什么要求,只要和構(gòu)造函數(shù)中的順序保持一致就可以了?,F(xiàn)在如果再增加一種測試情況,只需要在靜態(tài)方法 words 中添加相應的數(shù)組即可,不再需要復制粘貼出一個新的方法出來了。
這種參數(shù)化的測試用例寫法,很適用于一些共用的功能方法。



測試異常@Test(expected=XXXException.class)

異常測試是 JUnit4 中的最大改進。舊式的異常測試是在拋出異常的代碼中放入 try 塊,然后在 try 塊的末尾加入一個 fail() 語句。
例如,該方法測試被零除拋出一個 ArithmeticException:

?

public?void?testDivisionByZero()?{
try?{
int?n?=?2?/?0;
fail("Divided?by?zero!");
}

catch?(ArithmeticException?success)?{
assertNotNull(success.getMessage());
}

}


該方法不僅難看,而且寫起來也繁瑣。在 JUnit 4 中,我們現(xiàn)在可以編寫拋出異常的代碼,并使用注釋來聲明該異常是預期的:

???@Test(expected?=?BusinessException.class)public?void?testExecuteNameEmpty()?throws?Exception?{BookList?bListAction?=?new?BookList();bListAction.setName("");bListAction.execute();} 附被測試代碼(如果輸入name為empty,則拋出BusinessException,若name不為"liming",則拋出MessageException異常): ????@Overridepublic?String?execute()?throws?Exception?{if?(StringUtils.isEmpty(name))?{throw?new?BusinessException("~",?"name?cant't?empty.");}if?(!StringUtils.equals("liming",?name.trim()))?{throw?new?MessageException(name?+?"?have?no?limits.");}Map?ret?=?serviceCall.call(JMockService.queryDtlInfo,?null);orderId?=?(String)?ret.get("OrderId");dataList?=?(List)?ret.get("Data");return?SUCCESS;}


參數(shù)化測試

為了保證單元測試的嚴謹性,我們經(jīng)常要模擬很多種輸入?yún)?shù),來確定我們的功能代碼是可以正常工作的,為此我們編寫大量的單元測試方法??墒沁@些測試方法都是大同小異:代碼結(jié)構(gòu)都是相同的,不同的僅僅是測試數(shù)據(jù)和期望輸出值。
JUnit4 的參數(shù)化測試方法給我們提供了更好的方法,將測試方法中相同的代碼結(jié)構(gòu)提取出來,提高代碼的重用度,減少復制粘貼代碼的痛苦。
例如下面的功能代碼(格式化字符串,將駝峰規(guī)則的字符串以"_"分隔):

public?class?WordDealUtil?{public?static?String?wordFormat4DB(String?name)?{if?(name?==?null)?{return?null;}Pattern?p?=?Pattern.compile("[A-Z]");Matcher?m?=?p.matcher(name);StringBuffer?sb?=?new?StringBuffer();while?(m.find())?{if?(m.start()?!=?0)?{m.appendReplacement(sb,?("_"?+?m.group()).toLowerCase());}}return?m.appendTail(sb).toString().toLowerCase();}}沒有使用參數(shù)化的測試用例代碼:?public?class?WordDealUtilTest?{/***?測試?null?時的處理情況*/@Testpublic?void?wordFormat4DBNull()?{String?target?=?null;String?result?=?WordDealUtil.wordFormat4DB(target);assertNull(result);}/***?測試空字符串的處理情況*/@Testpublic?void?wordFormat4DBEmpty()?{String?target?=?"";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("",?result);}/***?測試當首字母大寫時的情況*/@Testpublic?void?wordFormat4DBegin()?{String?target?=?"EmployeeInfo";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("employee_info",?result);}/***?測試當尾字母為大寫時的情況*/@Testpublic?void?wordFormat4DBEnd()?{String?target?=?"employeeInfoA";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("employee_info_a",?result);}/***?測試多個相連字母大寫時的情況*/@Testpublic?void?wordFormat4DBTogether()?{String?target?=?"employeeAInfo";String?result?=?WordDealUtil.wordFormat4DB(target);assertEquals("employee_a_info",?result);}}

看以上測試用例代碼,結(jié)構(gòu)相似,只是輸入值與期望輸出不同而已,但我們要拷貝很多代碼。
使用參數(shù)化的測試用例代碼:

@SuppressWarnings("unchecked")@RunWith(Parameterized.class)public?class?WordDealUtilTestWithParam?{private?String?expected;private?String?target;@Parameterspublic?static?Collection?words()?{return?Arrays.asList(new?Object[][]?{{?"employee_info",?"employeeInfo"?},??//?測試一般的處理情況{?null,?null?},?????????????????????????//?測試?null?時的處理情況{?"",?""?},?????????????????????????????//?測試空字符串時的處理情況{?"employee_info",?"EmployeeInfo"?},????//?測試當首字母大寫時的情況{?"employee_info_a",?"employeeInfoA"?},?//?測試當尾字母為大寫時的情況{?"employee_a_info",?"employeeAInfo"?}??//?測試多個相連字母大寫時的情況});}/***?參數(shù)化測試必須的構(gòu)造函數(shù)*?@param?expected?????期望的測試結(jié)果,對應參數(shù)集中的第一個參數(shù)*?@param?target?????測試數(shù)據(jù),對應參數(shù)集中的第二個參數(shù)*/public?WordDealUtilTestWithParam(String?expected,?String?target)?{this.expected?=?expected;this.target?=?target;}/***?測試將?Java?對象名稱到數(shù)據(jù)庫名稱的轉(zhuǎn)換*/@Testpublic?void?wordFormat4DB()?{Assert.assertEquals(expected,?WordDealUtil.wordFormat4DB(target));}}

很明顯,代碼簡單且很清晰了。在靜態(tài)方法 words 中,我們使用二維數(shù)組來構(gòu)建測試所需要的參數(shù)列表,其中每個數(shù)組中的元素的放置順序并沒有什么要求,只要和構(gòu)造函數(shù)中的順序保持一致就可以了?,F(xiàn)在如果再增加一種測試情況,只需要在靜態(tài)方法 words 中添加相應的數(shù)組即可,不再需要復制粘貼出一個新的方法出來了。
這種參數(shù)化的測試用例寫法,很適用于一些共用的功能方法。

總結(jié)

以上是生活随笔為你收集整理的JUnit4用法详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。