一.Mock的使用場(chǎng)景:
比如以下場(chǎng)景:
1. mock掉外部依賴的應(yīng)用的HSF service的調(diào)用,比如uic,tp 的hsf服務(wù)依賴。
2. 對(duì)DAO層(訪問(wèn)mysql、oracle、tair、tfs等底層存儲(chǔ))的調(diào)用mock等。
3. 對(duì)系統(tǒng)間異步交互notify消息的mock。
4. 對(duì)method_A里面調(diào)用到的method_B 的mock 。
5. 對(duì)一些應(yīng)用里面自己的 class(abstract, final, static),interface,annotation ,enum,native等的mock。
二. Mock工具的原理:
1. record階段:錄制期望。也可以理解為數(shù)據(jù)準(zhǔn)備階段。創(chuàng)建依賴的class 或interface或method ,模擬返回的數(shù)據(jù),及調(diào)用的次數(shù)等。
2. replay階段:通過(guò)調(diào)用被測(cè)代碼,執(zhí)行測(cè)試。期間會(huì)invoke 到 第一階段record的mock對(duì)象或方法。
3. verify階段:驗(yàn)證??梢则?yàn)證調(diào)用返回是否正確。及mock的方法調(diào)用次數(shù),順序等。
三. Mock的兩種方式:
1. Behavior-oriented(Expectations & Verifications) ?;
2. State-oriented(MockUp) ? 。
通俗點(diǎn)講,Behavior-oriented是基于行為的mock,對(duì)mock目標(biāo)代碼的行為進(jìn)行模仿,更像黑盒測(cè)試。State-oriented 是基于狀態(tài)的mock,是站在目標(biāo)測(cè)試代碼內(nèi)部的。可以對(duì)傳入的參數(shù)進(jìn)行檢查、匹配,才返回某些結(jié)果,類似白盒。而State-oriented的 new MockUp基本上可以mock任何代碼或邏輯。非常強(qiáng)大。
四. Mock使用的簡(jiǎn)單例子:
1. Behavior-oriented(Expectations & Verifications) 方式的簡(jiǎn)單運(yùn)用
@RunWith(JMockit.class)
publicclassApplyServiceImplTest {
@Tested
privateApplyServiceImplapplyServiceImpl; ? ?//被測(cè)試的類
@Injectable
privateCustomerMappercustomerMapper; ? ?//測(cè)試函數(shù)使用到的外部類
@Test
publicvoidtestSendConfrimBorrowSms_Success() {
//開(kāi)始錄制期望數(shù)據(jù)
newExpectations() {
{
//指定要mock的函數(shù),該函數(shù)為被測(cè)試函數(shù)中使用的用戶數(shù)查詢函數(shù)
customerMapper.selectByPrimaryKey(anyLong);
//指定mock函數(shù)需要返回的結(jié)果值
result= getCustomerVo();
}
};
//執(zhí)行被測(cè)試函數(shù)邏輯
String applyNo ="10389278638798123";
Long userId = 500000975l;
intresutls =applyServiceImpl.sendConfrimBorrowSms(applyNo, userId);
//驗(yàn)證測(cè)試結(jié)果是否達(dá)到預(yù)期
assertEquals(1, resutls);
}
2. State-oriented(MockUp) 方式的簡(jiǎn)單運(yùn)用
采用MockUp的方式,可以mock任意的mock對(duì)象或方法,因?yàn)樗苯痈膶?xiě)了原method的實(shí)現(xiàn)邏輯,直接返回需要的數(shù)據(jù)
@Test
publicvoidtestMethodA() {
//對(duì)CustomerManager的函數(shù)進(jìn)行mock(被mock的類和函數(shù)需是被測(cè)試函數(shù)中被調(diào)用的類和函數(shù))
newMockUp() {
@mockit.Mock
publicvoid$clinit() {
//1、如CustomerManager中有初始化的靜態(tài)塊時(shí),$clinit不可缺省
//2、如果使用CustomerManager的帶參構(gòu)造函數(shù),需使用jmockit的帶參構(gòu)造方式,如:
//publicvoid$init(String version) {
// ? ? ?實(shí)現(xiàn)預(yù)期的操作,如果需要mock掉,不想做任何處理,這里空著就可以
//}
}
//指定要mock的函數(shù)(函數(shù)的聲明要與CustomerManager中的保持一致)
@mockit.Mock
public Customer selectByPrimaryKey(Long id){
//修改CustomerManager類中的selectByPrimaryKey的實(shí)現(xiàn)邏輯,返回mock的期望值
Customer customer = new Customer();
customer.setName("王小賤");
returncustomer;
}
};
//執(zhí)行被測(cè)試函數(shù)邏輯
String applyNo ="10389278638798123";
Long userId = 500000975l;
Customerresutls =applyServiceImpl.queryUserInfo(applyNo, userId);
//驗(yàn)證測(cè)試結(jié)果是否達(dá)到預(yù)期
assertEquals("王小賤", resutls.getName);
}