一.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() {
//開始錄制期望數(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)樗苯痈膶懥嗽璵ethod的實(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);
}