前言
在現(xiàn)在的軟件開(kāi)發(fā)中,由于軟件的復(fù)雜度越來(lái)越高,業(yè)務(wù)也覆蓋很廣,各個(gè)業(yè)務(wù)模塊業(yè)務(wù)錯(cuò)綜復(fù)雜。這樣就需要我們需要團(tuán)隊(duì)開(kāi)發(fā),在我們團(tuán)隊(duì)中開(kāi)發(fā)人員的經(jīng)驗(yàn)、代碼風(fēng)格樣式都不一致,以及缺乏統(tǒng)一的標(biāo)準(zhǔn),從而導(dǎo)致我們的整個(gè)項(xiàng)目的的代碼難以閱讀,不便于后期維護(hù)。這幾天在研究代碼質(zhì)量管理,根據(jù)在網(wǎng)上搜集的資料及跟前輩學(xué)的一點(diǎn)經(jīng)驗(yàn)整理一下,有需要的同學(xué)們可以查看,也便于以后自己回顧。
主要對(duì)下面的七塊進(jìn)行分析
編碼格式規(guī)范
代碼重復(fù)
代碼覆蓋率
依賴項(xiàng)分析
復(fù)雜度監(jiān)控
JAVA模擬技術(shù)
代碼評(píng)審和重構(gòu)
接下來(lái)的使用Eclipse 插件來(lái)揭示這些分析領(lǐng)域:
編碼格式規(guī)范:codeStyle和CheckStyle
代碼重復(fù):PMD 的 CPD
代碼覆蓋率:Coverlipse或者Emma
依賴項(xiàng)分析:JDepend
復(fù)雜度監(jiān)控:Metrics
Java模擬技術(shù):EasyMock、PowerMock
代碼評(píng)審和重構(gòu):Jupiter
編碼格式規(guī)范
codestyle介紹
統(tǒng)一的代碼規(guī)范能提高代碼的可讀性、可維護(hù)性。
一般規(guī)則和格式規(guī)范:如代碼縮進(jìn)、程序塊規(guī)范、每行最大代碼長(zhǎng)度;
命名規(guī)范:如包名、類名、接口名、枚舉、屬性名、方法名、參數(shù)名等命名規(guī)則;
文檔規(guī)范:如類文件頭注釋、變量注釋、方法注釋等;
編程規(guī)范:如異常、并發(fā)、多線程等;
其它規(guī)范:如日志格式等。
圖1
可以導(dǎo)入代碼格式,實(shí)現(xiàn)統(tǒng)一。
checkstyle介紹
安裝checkstyle 的Eclipse插件
1.下載地址:
http://pan.baidu.com/s/1o6LOSwM
2.解壓
net.sf.eclipsecs-updatesite_5.6.1.201306282206-bin.zip文件,到系統(tǒng)路徑下。如:D:geyouchaoeclipse-pluginscs(注:一定不用起名為checkstyle,不知道為什么此名就是安裝不成功),此文件夾下有兩個(gè)文件夾features、plugins。
3.我們使用link的方式安裝。在Eclipse的dropins文件夾下新建checkstyle.link文件,內(nèi)容為:
path=D:\geyouchao\eclipse-plugins\cs
4.關(guān)閉Eclipse,重啟。然后在Eclipse的window》Preferences下就可以看到checkstyle菜單,安裝成功,如下圖
圖2
使用checkstyle
自定義CheckStyle規(guī)則,下面是我定義的CheckStyle模板,然后導(dǎo)入
圖3
把新導(dǎo)入的,設(shè)置為默認(rèn)
圖4
可以修改其中的值,點(diǎn)擊“Configure…”按鈕。
圖5
下面是我自定義的CheckStyle.xml文件,供參考。
<xml version="1.0"encoding="UTF-8">
<!DOCTYPE module PUBLIC "-//PuppyCrawl//DTD Check Configuration 1.2//EN""http://www.puppycrawl.com /dtds/configuration_1_2.dtd">
<module name="Checker">
<propertyname="severity" value="warning"/>
<property name="charset" value="UTF-8"/>
<!-- 長(zhǎng)度方面的檢查 -->
<!-- 文件長(zhǎng)度不超過(guò)1500行 -->
<module name="FileLength">
<property name="max" value="1500" />
</module>
<module name="TreeWalker">
<!-- javadoc的檢查 -->
<!-- 檢查所有的interface和class -->
<module name="JavadocType" />
<!-- 命名方面的檢查 -->
<!-- 局部的final變量,包括catch中的參數(shù)的檢查 -->
<module name="LocalFinalVariableName" />
<!-- 局部的非final型的變量,包括catch中的參數(shù)的檢查 -->
<module name="LocalVariableName" />
<!-- 包名的檢查(只允許小寫(xiě)字母) -->
<module name="PackageName">
<property name="format"value="^[a-z]+ (.[a-z][a-z0-9]*)*$" />
</module>
<!--僅僅是static型的變量(不包括static final型 )的檢查 -->
<module name="StaticVariableName" />
<!-- 類型(Class或Interface)名的檢查 -->
<module name="TypeName" />
<!-- 非static型變量的檢查 -->
<module name="MemberName" />
<!-- 方法名的檢查 -->
<module name="MethodName" />
<!-- 方法的參數(shù)名 -->
<modulename="ParameterName " />
<!-- 常量名的檢查 -->
<module name="ConstantName" />
<!-- 沒(méi)用的import檢查,比如:1.沒(méi)有被用到 2.重復(fù)的 3.import java.lang的 4.import 與該類在同一個(gè)package的 -->
<module name="UnusedImports" />
<!-- 每行不超過(guò)150個(gè)字-->
<module name="LineLength">
<property name="max" value="150" />
</module>
<!-- 方法不超過(guò)150行 -->
<module name="MethodLength">
<property name="tokens" value="METHOD_DEF"/>
<property name="max"value="150" />
</module>
<!-- 方法的參數(shù)個(gè)數(shù)不超過(guò)5個(gè)。并且不對(duì)構(gòu)造方法進(jìn)行檢查-->
<module name="ParameterNumber">
<property name="max" value="5" />
<property name="tokens" value="METHOD_DEF"/>
</module>
<!-- 空格檢查 -->
<!-- 允許方法名后緊跟左邊圓括號(hào)"(" -->
<module name="MethodParamPad" />
<!-- 在類型轉(zhuǎn)換時(shí),不允許左圓括號(hào)右邊有空格,也不允許與右圓括號(hào)左邊有空格 -->
<module name="TypecastParenPad" />
<!-- 關(guān)鍵字 -->
<!--
每個(gè)關(guān)鍵字都有正確的出現(xiàn)順序。比如 public static final XXX 是對(duì)一個(gè)常量的聲明。如果使用 static
public final 就是錯(cuò)誤的
-->
<module name="ModifierOrder" />
<!-- 多余的關(guān)鍵字 -->
<module name="RedundantModifier" />
<!-- 對(duì)區(qū)域的檢查 -->
<!-- 不能出現(xiàn)空白區(qū)域 -->
<module name="EmptyBlock" />
<!-- 所有區(qū)域都要使用大括號(hào) -->
<module name="NeedBraces" />
<!-- 多余的括號(hào) -->
<module name="AvoidNestedBlocks">
<property name="allowInSwitchCase" value="true"/>
</module>
<!-- 編碼方面的檢查 -->
<!-- 不許出現(xiàn)空語(yǔ)句 -->
<module name="EmptyStatement" />
<!-- 不允許魔法數(shù) -->
<module name="MagicNumber">
<property name="tokens"value="NUM_DOUBLE, NUM_INT" />
</module>
<!-- 多余的throw -->
<module name="RedundantThrows" />
<!-- String的比較不能用!= 和 == -->
<module name="StringLiteralEquality" />
<!-- if最多嵌套3層 -->
<module name="NestedIfDepth">
<property name="max" value="3" />
</module>
<!-- try最多被嵌套2層 -->
<module name="NestedTryDepth">
<property name="max" value="2" />
</module>
<!-- clone方法必須調(diào)用了super.clone() -->
<module name="SuperClone" />
<!-- finalize 必須調(diào)用了super.finalize() -->
<module name="SuperFinalize" />
<!-- 不能catch java.lang.Exception -->
<module name="IllegalCatch">
<property name="illegalClassNames"value="java.lang.Exception" />
</module>
<!-- 確保一個(gè)類有package聲明 -->
<module name="PackageDeclaration" />
<!-- 一個(gè)方法中最多有3個(gè)return -->
<modulename="ReturnCount">
<property name="max" value="3" />
<property name="format" value="^$" />
</module>
<!--
根據(jù) Sun 編碼規(guī)范, class 或 interface 中的順序如下: 1.class 聲明。首先是 public,
然后是protected , 然后是 package level (不包括access modifier )最后是private .
(多個(gè)class放在一個(gè)java文件中的情況) 2.變量聲明。首先是 public, 然后是protected然后是 package
level (不包括access modifier )最后是private . (多個(gè)class放在一個(gè)java文件中的情況)
3.構(gòu)造函數(shù) 4.方法
-->
<module name="DeclarationOrder" />
<!-- 同一行不能有多個(gè)聲明 -->
<module name="MultipleVariableDeclarations" />
<!-- 不必要的圓括號(hào) -->
<module name="UnnecessaryParentheses" />
<!-- 檢查并確保所有的常量中的L都是大寫(xiě)的。因?yàn)樾?xiě)的字母l跟數(shù)字1太象了 -->
<module name="UpperEll" />
<!-- 檢查數(shù)組類型的定義是String[] args,而不是String args[] -->
<module name="ArrayTypeStyle" />
<!-- 檢查java代碼的縮進(jìn)默認(rèn)配置:基本縮進(jìn)4個(gè)空格,新行的大括號(hào):0。新行的case 4個(gè)空格
<module name="Indentation" />
</module>
</module>
下面是使用CheckStyle檢查過(guò)得代碼
圖6
常見(jiàn)錯(cuò)誤分析
常見(jiàn)的CheckStyle錯(cuò)誤有這些:
1.Type is missing a javadoc commentClass
缺少類型說(shuō)明
2.“{” should be on the previous line
“{” 應(yīng)該位于前一行
3.Methods is missing a javadoc comment
方法前面缺少javadoc注釋
4.Expected@throwstag for “Exception”
在注釋中希望有@throws的說(shuō)明
5.“.” Is preceeded with whitespace “.”
前面不能有空格
6.“.” Is followed by whitespace“.”
后面不能有空格
7.“=” is not preceeded with whitespace
“=” 前面缺少空格
8.“=” is not followed with whitespace
“=” 后面缺少空格
9.“}” should be on the same line
“}” 應(yīng)該與下條語(yǔ)句位于同一行
10.Unused@paramtag for “unused”
沒(méi)有參數(shù)“unused”,不需注釋
11.Variable “CA” missing javadoc
變量“CA”缺少javadoc注釋
12.Line longer than 80characters
行長(zhǎng)度超過(guò)80
13.Line contains a tab character
行含有”tab” 字符
14.Redundant “Public” modifier
冗余的“public”modifier
15.Final modifier out of order with the JSL
suggestionFinal modifier的順序錯(cuò)誤
16.Avoid using the “.*” form of import
Import格式避免使用“.*”
17.Redundant import from the same package
從同一個(gè)包中Import內(nèi)容
18.Unused import-java.util.list
Import進(jìn)來(lái)的java.util.list沒(méi)有被使用
19.Duplicate import to line 13
重復(fù)Import同一個(gè)內(nèi)容
20.Import from illegal package
從非法包中 Import內(nèi)容
21.“while” construct must use “{}”
“while” 語(yǔ)句缺少“{}”
22.Variable “sTest1” must be private and haveaccessor method
變量“sTest1”應(yīng)該是private的,并且有調(diào)用它的方法
23.Variable “ABC” must match pattern“^[a-z][a-zA-Z0-9]*$”
變量“ABC”不符合命名規(guī)則“^[a-z][a-zA-Z0-9]*$”
24.“(” is followed by whitespace
“(” 后面不能有空格
25.“)” is proceeded by whitespace
“)” 前面不能有空格
代碼重復(fù)
PMD介紹
安裝PMD 的Eclipse插件
1.下載地址:
http://jingyan.baidu.com/article/1919 2ad835de6ee53e57073c.html
2.解壓
net.sourceforge.pmd.eclipse-3.2.6.v200903300643.zip文件,到系統(tǒng)路徑下。如:D:geyouchaoeclipse-pluginspmd,此文件夾下有兩個(gè)文件夾features、plugins。
3.我們使用link的方式安裝。在Eclipse的dropins文件夾下新建pmd.link文件,內(nèi)容為:
path=D:\geyouchao\eclipse-plugins\pmd
4.關(guān)閉Eclipse,重啟。然后在Eclipse的window》Preferences下就可以看到PMD菜單,安裝成功,如下圖
圖7
使用PMD
圖8
下面是PCD生成的重復(fù)代碼,可以對(duì)其中的代碼進(jìn)行分析,修改
圖9
代碼覆蓋率
Coverlipse介紹
安裝coverlipse 的Eclipse插件
1.下載地址:
https://sourceforge.net/projects/coverlipse /files/Coverlipse/
下載下圖中5個(gè)文件
圖10
1.解壓coverlipse-0.9.6.zip文件,到系統(tǒng)路徑下。如:D:geyouchaoeclipse-plugins coverlipse-0.9.6,此文件夾下有兩個(gè)文件夾features、plugins。
2.我們使用link的方式安裝。在Eclipse的dropins文件夾下新建coverlipse.link文件,內(nèi)容為:
path=D:\geyouchao\eclipse-plugins\coverlipse
3.關(guān)閉Eclipse,重啟。右鍵java代碼,點(diǎn)擊dubug,安裝成功,如下圖
圖11
依賴項(xiàng)分析
jdepend介紹
安裝jdepend 的Eclipse插件
1.下載地址:
http://andrei.gmxhome.de/ jdepend4eclipse/links.html
圖12
2.拷貝
de.loskutov.eclipse.jdepend_1.2.4.201406241900.jar文件,到Eclipse的dropins目錄下。如:D:geyouchaoeclipse4.2-xudropins。
3.關(guān)閉Eclipse,重啟。通過(guò)右鍵單擊源文件夾并選擇Run JDepend Analysis。一定要選擇一個(gè)含源代碼的源文件夾;否則看不到此菜單項(xiàng)。
圖13
使用jdepend
圖14
下面對(duì)jdepend的分析的結(jié)果簡(jiǎn)單介紹
圖15
1.Selected objects():選擇分析的包
2.Package:包全路徑
3.CC(concr.cl.):當(dāng)前行對(duì)應(yīng)包的具體類的數(shù)量。
4.AC(abstr.cl.):當(dāng)前行對(duì)應(yīng)包的抽象類和接口的數(shù)量。
5.Ca(aff.):依賴于被分析package的其他package的數(shù)量,用于衡量pacakge的職責(zé)。即有多少包調(diào)用了它。(AfferentCouplings)
6.Ce(eff.):被分析package的類所依賴的其他package的數(shù)量,用于衡量package的獨(dú)立性。即它調(diào)用了多少其他包。(EfferentCouplings)
7.A:被分析package中的抽象類和接口與所在package所有類數(shù)量的比例,取值范圍為0-1。(Abstractness)
8.I:I=Ce/(Ce+Ca),用于衡量package的不穩(wěn)定性,取值范圍為0-1。I=0表示最穩(wěn)定,I=1表示最不穩(wěn)定。即如果這個(gè)類不調(diào)用任何其他包,則它是最穩(wěn)定的。(Instability)
9.D:分析package和理想曲線A+I(xiàn)=1的垂直距離,用于衡量package在穩(wěn)定性和抽象性之間的平衡。(Distance)
理想的package要么完全是抽象類和穩(wěn)定(x=0,y=1),要么完全是具體類和不穩(wěn)定(x=1,y=0)。取值范圍為0-1,
D=0表示完全符合理想標(biāo)準(zhǔn),
D=1表示package最大程度地偏離了理想標(biāo)準(zhǔn)。即你的包要么全是接口,不調(diào)用任何其他包(完全是抽象類和穩(wěn)定),要么是具體類,不被任何其他包調(diào)用。
10.Cycle!:循環(huán)依賴
11. Package with cycle:包與包直接有循環(huán)調(diào)用
12. Depends
upon-efferentdependencies:依賴的包
13. Used by-afferentdependencies:被引用的包
圖16
Instability:不穩(wěn)定
Abstractness:抽象性
問(wèn)題分析
圖17
針對(duì)上圖中Cycle!列中有感嘆號(hào)圖標(biāo)問(wèn)題,是因?yàn)橐陨先齻€(gè)包中的類有傳遞依賴,故出現(xiàn)此警告。
解決辦法:
把其中的某個(gè)或者某些類再單獨(dú)抽出新包,解決此問(wèn)題。
復(fù)雜度監(jiān)控
metrics(量度)介紹
安裝metrics 的Eclipse插件
1.下載地址:
https://sourceforge.net/projects/metrics/
圖18
圖19
圖20
圖21
2.解壓updatesite_1.3.6.zip文件,
net.sourceforge.metrics.updatesite文件夾下有features和plugins分別拷貝到Eclipse的對(duì)應(yīng)目錄下。如:D:geyouchaoeclipse4.2-xuplugins等。
3.關(guān)閉Eclipse,重啟。然后在Eclipse的window》Preferences下就可以看到Metrics Preferences菜單,安裝成功,如下圖
圖22
設(shè)置metrics參數(shù)
下圖是metrics提供的配置項(xiàng),下面對(duì)各個(gè)配置項(xiàng)進(jìn)行解釋
圖23
lack of cohesion of methods:
介于0-1之間,0表示最有凝聚力,1表示完全沒(méi)有凝聚力。
1)如果所有方法都使用所有的實(shí)例字段,一個(gè)類是完全有凝聚力的
2)靜態(tài)方法和實(shí)例方法計(jì)數(shù),它還包括構(gòu)造函數(shù)、屬性的getter和setter,所有方法。
在Since Sonar 4.1中此量度已經(jīng)被刪除。
3) 子的數(shù)量NOC(Number ofchildren)子類在類的層次內(nèi),子類可以最直接地從屬于一類。隨著子類數(shù)量的增大,重用也增加了。但父類抽象的表示可能減少,即一些子類可能不是父類真正的成員,同時(shí),測(cè)試數(shù)量(用來(lái)檢查每個(gè)子類在操作前后的要求)也將增加。
4) 方法中聚合的不足LCOM(Lack ofcohesion in Methods)
一個(gè)類內(nèi)的每種方法訪問(wèn)一個(gè)或多個(gè)屬性(也稱實(shí)例變量)。LCOM是訪問(wèn)一個(gè)或多個(gè)相同屬性方法的數(shù)量
如果LCOM很大,則說(shuō)明方法可以通過(guò)屬性與其他方法耦合,這就增加了類設(shè)計(jì)的復(fù)雜性。通常,對(duì)LCOM值很大的類,可以把它分為兩個(gè)或多個(gè)單獨(dú)的類,這樣每個(gè)類能的設(shè)計(jì)更方便。
這里講的耦合和聚合與傳統(tǒng)軟件中講的是一樣的。我們希望高聚合和低耦合,即保持低的LCOM.但在某些時(shí)候,LCOM很大也是合理的。
5)每個(gè)類的加權(quán)方法WMC(Weighted Methodsper Class)
6)Out-of-range:超出范圍,溢出
下面是metric的安全范圍設(shè)置,在此頁(yè)面中可以設(shè)置每項(xiàng)指標(biāo)的安全范圍。若警告啟用,指標(biāo)值超出我們?cè)O(shè)置的安全范圍就好發(fā)出警告。
圖24
使用metrics
1.右鍵單擊您的項(xiàng)目并選擇 Properties 菜單。在結(jié)果窗口中,選擇 EnableMetrics plugin 復(fù)選框并單擊 OK:
圖25
2.從 Eclipse 中選擇 Window 菜單打開(kāi) Metrics 視圖,然后選擇 Show View | Other...。
3.選擇 Metrics | Metrics View 打開(kāi)如圖 13 中顯示的窗口。您需要使用Java 透視圖并重新構(gòu)建項(xiàng)目,從而顯示這些度量值。
圖26
注:一定要重新構(gòu)建項(xiàng)目
圖27
Java 模擬技術(shù)(mock)
Mock是什么
Mock通常是指,在測(cè)試一個(gè)對(duì)象A時(shí),我們構(gòu)造一些假的對(duì)象來(lái)模擬與A之間的交互,而這些Mock對(duì)象的行為是我們事先設(shè)定且符合預(yù)期。通過(guò)這些Mock對(duì)象來(lái)測(cè)試A在正常邏輯,異常邏輯或壓力情況下工作是否正常。
引入Mock最大的優(yōu)勢(shì)在于:Mock的行為固定,它確保當(dāng)你訪問(wèn)該Mock的某個(gè)方法時(shí)總是能夠獲得一個(gè)沒(méi)有任何邏輯的直接就返回的預(yù)期結(jié)果。
Mock Object的使用通常會(huì)帶來(lái)以下一些好處:
隔絕其他模塊出錯(cuò)引起本模塊的測(cè)試錯(cuò)誤。
隔絕其他模塊的開(kāi)發(fā)狀態(tài),只要定義好接口,不用管他們開(kāi)發(fā)有沒(méi)有完成。
一些速度較慢的操作,可以用MockObject代替,快速返回。
對(duì)于分布式系統(tǒng)的測(cè)試,使用Mock Object會(huì)有另外兩項(xiàng)很重要的收益:
通過(guò)Mock Object可以將一些分布式測(cè)試轉(zhuǎn)化為本地的測(cè)試
將Mock用于壓力測(cè)試,可以解決測(cè)試集群無(wú)法模擬線上集群大規(guī)模下的壓力
mock技術(shù)的目的和作用是模擬一些在應(yīng)用中不容易構(gòu)造或者比較復(fù)雜的對(duì)象,從而把測(cè)試與測(cè)試邊界以外的對(duì)象隔離開(kāi)。
Mock應(yīng)用場(chǎng)景
在使用Mock的過(guò)程中,發(fā)現(xiàn)Mock是有一些通用性的,對(duì)于一些應(yīng)用場(chǎng)景,是非常適合使用Mock的:
真實(shí)對(duì)象具有不可確定的行為(產(chǎn)生不可預(yù)測(cè)的結(jié)果,如股票的行情)
真實(shí)對(duì)象很難被創(chuàng)建(比如具體的web容器)
真實(shí)對(duì)象的某些行為很難觸發(fā)(比如網(wǎng)絡(luò)錯(cuò)誤)
真實(shí)情況令程序的運(yùn)行速度很慢
真實(shí)對(duì)象有用戶界面
測(cè)試需要詢問(wèn)真實(shí)對(duì)象它是如何被調(diào)用的(比如測(cè)試可能需要驗(yàn)證某個(gè)回調(diào)函數(shù)是否被調(diào)用了)
真實(shí)對(duì)象實(shí)際上并不存在(當(dāng)需要和其他開(kāi)發(fā)小組,或者新的硬件系統(tǒng)打交道的時(shí)候,這是一個(gè)普遍的問(wèn)題)
當(dāng)然,也有一些不得不Mock的場(chǎng)景:
一些比較難構(gòu)造的Object:這類Object通常有很多依賴,在單元測(cè)試中構(gòu)造出這樣類通常花費(fèi)的成本太大。
執(zhí)行操作的時(shí)間較長(zhǎng)Object:有一些Object的操作費(fèi)時(shí),而被測(cè)對(duì)象依賴于這一個(gè)操作的執(zhí)行結(jié)果,例如大文件寫(xiě)操作,數(shù)據(jù)的更新等等,出于測(cè)試的需求,通常將這類操作進(jìn)行Mock。
異常邏輯:一些異常的邏輯往往在正常測(cè)試中是很難觸發(fā)的,通過(guò)Mock可以人為的控制觸發(fā)異常邏輯。
在一些壓力測(cè)試的場(chǎng)景下,也不得不使用Mock,例如在分布式系統(tǒng)測(cè)試中,通常需要測(cè)試一些單點(diǎn)(如namenode,jobtracker)在壓力場(chǎng)景下的工作是否正常。而通常測(cè)試集群在正常邏輯下無(wú)法提供足夠的壓力(主要原因是受限于機(jī)器數(shù)量),這時(shí)候就需要應(yīng)用Mock去滿足。
在這些場(chǎng)景下,我們應(yīng)該如何去做Mock的工作了,一些現(xiàn)有的Mock工具可以幫助我們進(jìn)行Mock工作。
EasyMock應(yīng)用
Easymock官網(wǎng):
http://easymock.org/
EasyMock 是早期比較流行的MocK測(cè)試框架。它提供對(duì)接口的模擬,能夠通過(guò)錄制、回放、檢查三步來(lái)完成大體的測(cè)試過(guò)程,可以驗(yàn)證方法的調(diào)用種類、次數(shù)、順序,可以令 Mock 對(duì)象返回指定的值或拋出指定異常。通過(guò) EasyMock,我們可以方便的構(gòu)造 Mock 對(duì)象從而使單元測(cè)試順利進(jìn)行。
EasyMock 是采用 MIT license 的一個(gè)開(kāi)源項(xiàng)目
使用EasyMock大致可以劃分為以下幾個(gè)步驟:
① 使用 EasyMock 生成 Mock 對(duì)象;
② 錄制 Mock 對(duì)象的預(yù)期行為和輸出;
③ 將 Mock 對(duì)象切換到 播放 狀態(tài);
④ 調(diào)用 Mock 對(duì)象方法進(jìn)行單元測(cè)試;
⑤ 對(duì) Mock 對(duì)象的行為進(jìn)行驗(yàn)證。
mockito應(yīng)用
mockito官網(wǎng)
https://code.google.com/p/mockito/
由于官網(wǎng)上不了,可以到csdn上下載
http://download.csdn.net/download /wjjiang917/5519381
是EasyMock之后流行的mock工具。相對(duì)EasyMock學(xué)習(xí)成本低,而且具有非常簡(jiǎn)潔的API,測(cè)試代碼的可讀性很高。
使用mockito大致可以劃分為以下幾個(gè)步驟:
① 使用 mockito 生成 Mock 對(duì)象;
② 定義(并非錄制) Mock 對(duì)象的行為和輸出(expectations部分);
③ 調(diào)用 Mock 對(duì)象方法進(jìn)行單元測(cè)試;
④ 對(duì) Mock 對(duì)象的行為進(jìn)行驗(yàn)證。
PowerMock應(yīng)用
PowerMock官網(wǎng)
https://code.google.com/p/powermock/
這個(gè)工具是在EasyMock和Mockito上擴(kuò)展出來(lái)的,目的是為了解決EasyMock和Mockito不能解決的問(wèn)題,比如對(duì)static, final, private方法均不能mock。其實(shí)測(cè)試架構(gòu)設(shè)計(jì)良好的代碼,一般并不需要這些功能,但如果是在已有項(xiàng)目上增加單元測(cè)試,老代碼有問(wèn)題且不能改時(shí),就不得不使用這些功能了。
PowerMock 在擴(kuò)展功能時(shí)完全采用和被擴(kuò)展的框架相同的API, 熟悉 PowerMock 所支持的模擬框架的開(kāi)發(fā)者會(huì)發(fā)現(xiàn) PowerMock 非常容易上手。PowerMock 的目的就是在當(dāng)前已經(jīng)被大家所熟悉的接口上通過(guò)添加極少的方法和注釋來(lái)實(shí)現(xiàn)額外的功能。目前PowerMock 僅擴(kuò)展了 EasyMock 和 mockito,需要和EasyMock或Mockito配合一起使用。
因?yàn)閮?nèi)容實(shí)在是太多了,小編在此就不做過(guò)多的介紹了,想了解更多的Java知識(shí)可以關(guān)注小編!






