本節(jié)是單元測(cè)試系列的第二篇。重點(diǎn)講解如何使用Mock/Stub和依賴注入技術(shù)進(jìn)行單元測(cè)試。關(guān)于工具JUnit等則不做累贅介紹。 希望通過(guò)本章能夠幫助大家開(kāi)始單元測(cè)試的有益實(shí)踐,與大家共勉!
單元測(cè)試(技能篇)
一、Stub技術(shù)
這是最為古老的一種測(cè)試技能。通過(guò)類層次上的替換實(shí)現(xiàn)了對(duì)待測(cè)環(huán)境的模擬。
實(shí)現(xiàn)的時(shí)候有兩種途徑:
1、重寫實(shí)際類,在測(cè)試時(shí),先于實(shí)際類加載,即覆蓋。如:我們?cè)?/span>unittest/stub文件夾下針對(duì)于每一個(gè)重寫類都有相同的包結(jié)構(gòu)和類名:

在類路徑中優(yōu)先加載:

2、在實(shí)際代碼中添加判斷。比如,如果當(dāng)前是測(cè)試環(huán)境if(isUT)執(zhí)行XX操作,截?cái)嗾嬲枰龅氖隆?/span>
publicvoid sendCommand(int cmdCode)
{
if(isUT())
{
//...
}
else
{
//...
}
}
Stub技術(shù)的問(wèn)題就在于我們?cè)谥貙戇@些類的時(shí)候,不僅僅要關(guān)注接口,還要關(guān)注其內(nèi)部邏輯。如果你只是簡(jiǎn)單的返回一個(gè)固定的響應(yīng),會(huì)很簡(jiǎn)單。但是對(duì)于每一次運(yùn)行需要根據(jù)不同的輸入返回不同的輸出時(shí)方法內(nèi)部的處理就會(huì)復(fù)雜的多。
由于實(shí)現(xiàn)的難度,所以,使用時(shí)就要注意:有高價(jià)值、重用度高、數(shù)量少。這就是說(shuō),重寫一個(gè)類,就可以有一大批類可以用。
二、Mock技術(shù)
Mock是目前單元測(cè)試中最常用的。用來(lái)在對(duì)象層次上實(shí)現(xiàn)細(xì)類度替換十分方便。
當(dāng)我們?cè)跍y(cè)試中,需要其它類/接口的一個(gè)方法時(shí),我們可以通過(guò)繼承/實(shí)現(xiàn)其一個(gè)子類對(duì)象來(lái)替換實(shí)際對(duì)象。在Mock子類中將需要的方法直接返回需要的結(jié)果就行了。
privateclass Mock_QueryCtrl extends QueryCtrl
{
public List queryNEList()
{
List neList = new ArrayList();
//直接填充并返回你需要的數(shù)據(jù)...
return neList;
}
}
同樣,我們也可以通過(guò)測(cè)試待測(cè)類的子類來(lái)測(cè)試待測(cè)類。這對(duì)于被測(cè)方法使用了自身類的方法時(shí)很適用。
三、依賴注入
單元測(cè)試的一個(gè)關(guān)鍵就是替換。類層次上的替換,通過(guò)在類路徑中提前加載就可以實(shí)現(xiàn)。而在對(duì)象層次上,java的反射機(jī)制提供了很好的幫助。
1).獲取/注入私有屬性
2).執(zhí)行私有方法
附:注入私有屬性的實(shí)現(xiàn):
publicvoid setFieldObject(Object instance, String fieldName, Object
value)
throws IllegalArgumentException, IllegalAccessException,
NoSuchFieldException {
Field field = null;
Class c = instance.getClass();
do {
try
{
field = c.getDeclaredField(fieldName);
} catch (SecurityException e)
{
e.printStackTrace();
} catch (NoSuchFieldException e)
{
c = c.getSuperclass();
}
}
while (c.getName() != "java.lang.Object" && field
== null);
if (field != null)
{
field.setAccessible(true);
field.set(instance, value);
}
else
{
thrownew NoSuchFieldException(fieldName);
}
}
注:這是一個(gè)簡(jiǎn)單實(shí)現(xiàn),實(shí)際中需要優(yōu)化。
四、實(shí)例:
下例演示了如何測(cè)試類NEListTable的ShowNETable()方法。其中注意的是,方法中調(diào)用了類QueryCtrl的queryNEList()方法。
待測(cè)類:
publicclass NEListTable
{
QueryCtrl ctrl = null;
publicvoid ShowNETable()
{
List neList =
ctrl.queryNEList();
for(int i =
0;i<neList.size();i++)
{
//將neList轉(zhuǎn)換為表格行
}
//顯示表格...
}
}
publicclass QueryCtrl {
public List queryNEList()
{
returnnull;
}
}
測(cè)試類:
public class TestNEListTable extends TestCase
{
private
NEListTable table = null;
private
TestHelper helper = null;
public
void testShowNETable()
{
Mock_QueryCtrl ctrl = new
Mock_QueryCtrl();
helper.setObjectField(table,"ctrl",ctrl);//將Mock對(duì)象注入table
table.ShowNETable();
assertTrue(table.getRowCount()>0);
}
private
class Mock_QueryCtrl extends
QueryCtrl
{
public
List queryNEList()
{
List neList = new
ArrayList();
//返回你需要的數(shù)據(jù)...
return neList;
}
}
}
posted on 2008-07-10 22:14
wukaichun 閱讀(2020)
評(píng)論(4) 編輯 收藏 所屬分類:
test