Jmockit是一個超強大的ut mock工具, 與其他mock工具最大的特點是可以對final類, 靜態方法進行mock! 這是其他mock工具不可比的. 這也成爲我們選它做ut的原因. 多種mock工具特色比較:
http://code.google.com/p/jmockit/wiki/MockingToolkitComparisonMatrix
一 jmockit加載注意事項
1 由於jmockit用到了jdk1.5的instrument特性, 所以必需用1.5以上的jdk運行
2 如果junit版本是4.x, 需要4.8以上的版本, 而且在設置classpath時jmockit.jar的路徑要設置在junit.jar前. 這樣保證使用jmockit的runner加載junit
3 jmockit還自帶了ut覆蓋率統計工具, 將jmockit-coverage.jar的路徑加入classpath, 每次ut完成就會自動生成覆蓋率報告, 方便省心.
二 jmockit實用技巧之MockUp類應用
Jmockit提供了多種mock方式共開發者使用, 但給我感覺最有用的一個類就是MockUp. 用它幾乎能完成所有需要mock的操作:
<!--[if !supportLists]-->a) <!--[endif]-->mock接口. 使用MockUp.getMockInstance()方便mock接口, 特別是定義了多個方法的接口. 手工打樁需要寫一個此接口的假實現, 但測試中只調用了接口的一個方法, 造成了其他沒調用方法還要寫一堆沒用的實現. 用了MockUp打樁就只關注需要mock的方法即可:
package demo.jmockit;
public interface IService {
void doSth();
void doOtherthing();
}
接口中有兩個方法, 使用Mock返回一個mock對象時只關注被調用的方法doSth()即可:
package demo.jmockit;
import mockit.Mock;
import mockit.MockUp;
import mockit.Mockit;
import org.junit.Test;
public class TestCase {
@Test
public void testSth() throws Exception {
IService service = new MockUp<IService>() {
// 需要mock哪個方法就只寫哪個方法的mock實現, 其他方法都可以忽略
@Mock
public void doSth() {
System.out.println("this is mock implement");
}
}.getMockInstance();
// 調用mock方法
service.doSth();
// 最後做還原動作, 確保用例之間不相互影響. 也可以放到test case的teardown方法中
Mockit.tearDownMocks();
}
}
<!--[if !supportLists]-->b) <!--[endif]-->mock final類或靜態方法. 對於final類或靜態方法, 其他mock工具基本沒有好的辦法, 但用MockUp就非常簡單:
package demo.jmockit;
public class Utils {
public static String getFormatStr()throws Exception{
return "YYYY-mm-dd HH:MM:SS";
}
}
package demo.jmockit;
import mockit.Mock;
import mockit.MockUp;
import mockit.Mockit;
import org.junit.After;
import org.junit.Test;
public class TestCase {
@Test
public void testMockStaticMethod() {
// 打印mock前返回值
System.out.println(Utils.getFormatStr());
new MockUp<Utils>() {
//除了static關鍵字, 其他方法定義內容保持與被mock方法一致(包括異常定義)
@Mock
public String getFormatStr() throws Exception {
return "OtherFormat: dd-mm-YYYY";
}
};
// 打印mock後返回值
System.out.println(Utils.getFormatStr());
}
@After
public void tearDown() {
// 最後做還原動作, 確保用例之間不相互影響.
Mockit.tearDownMocks();
}
}