Mockito各場景使用介紹
場景1:某三方接口所有方法都需要Mock
實現方式1-配置configrution bean
實現方式2-在application context中配置mock bean
場景2:某三方接口部分方法mock
實現方式1-spy方式:
實現方式2-callRealMethod():
場景3:影響範圍只在單個測試類
實現方式1-使用ReflectionTestUtils解決依賴註入Mock對象
實現方式2-官方介紹的@mock,@injectMock方式
場景4.mock代理類
實現方式1-通過AddtionalAnswer.delegateto(instance)
場景1:某三方接口所有方法都需要Mock
實現方式1-配置configrution bean
step1:創建一個類如下:
@Configuration
public class WithdrawConfiguration {
@Bean
@Primary
public SauronBankService sauronBankService() {
SauronBankService mock = mock(SauronBankService.class);
BankCardDTO t = new BankCardDTO();
t.setBankId((short) 11);
t.setCardholder("hehe");
t.setCardId("32423423423");
t.setBankName("中國銀行 ");
t.setAcc_type((byte) 1);
t.setBranch_bank_name("武漢分行");
t.setProvince("湖北省");
t.setCity("武漢市");
when(mock.queryBankCard(anyInt(), anyLong(), Mockito.<String> any()))
.thenReturn(t);
return mock;
}
@Bean
@Primary
public MasspayClient masspayClient() {
// then return this.
MasspayClient client = Mockito.mock(MasspayClient.class);
MasspayResult<WithdrawResponse> withdrawResponseMasspayResult = new MasspayResult<>(
ResultCode.SUCCESS);
when(client.callLadon(any(WithdrawRequest.class)))
.thenReturn(withdrawResponseMasspayResult);
MasspayResult<CancelResponse> cancelResponseMasspayResult = new MasspayResult<>(
ResultCode.SUCCESS);
when(client.cancelCallLadon(any(CancelRequest.class)))
.thenReturn(cancelResponseMasspayResult);
return client;
}
}
step2.在application context中加載如下:
實現方式2-在application context中配置mock bean
step1:pom文件中加載mockito dependency
step2:在application context中聲明mock bean,參考如下:
<bean id="mockOrderManageFacade" class="org.mockito.Mockito"
factory-method="mock">
<constructor-arg value="me.ele.transcore.comm.facade.api.OrderManageFacade">
</constructor-arg>
</bean>
註意事項:
<!-- id必須和biz中autowired的屬性值一致,然後在測試類中@Resource該對象,stub該對象的方法指定返回數據 -->
<!-- 對其他測試類的影響:有關聯測試類調用該接口時,接口中的其他方法默認返回null;解決影響:在其他相關聯的測試指定返回值 -->
step3:在測試類中添加mock代碼,參考如下:
MockitoAnnotations.initMocks(this);//初始化mock bean
WithdrawCancelCallBackResponse mockResponse = new WithdrawCancelCallBackResponse();
mockResponse.setResultCode(
ResultCodeEnum.FAIL_WITHDRAW_CALLBACK_AMOUNT_NO_CONSISTENT
.getKey());//
Mockito.when(mockOrderManageFacade.withdrawCancelCallBack(
Mockito.any(WithdrawCancelCallBackRequest.class)))
.thenReturn(mockResponse);//mock為期望的response
場景2:某三方接口部分方法mock
- 部分mock解釋說明:部分mock是說一個類的方法有些是實際調用,有些是使用mockito的stubbing(樁實現)
- mockito實現部分mock的兩種方式:spy和callRealMethod()
- Spy類就可以滿足我們的要求。如果一個方法定制了返回值或者異常,那麽就會按照定制的方式被調用執行;如果一個方法沒被定制,那麽調用的就是真實類的方法。
- 如果我們定制了一個方法A後,再下一個測試方法中又想調用真實方法,那麽只需在方法A被調用前,調用Mockito.reset(spyObject)。
實現方式1-spy方式:
@Test
public void spy_Simple_demo(){
List<String> list = new LinkedList<String>();
List<String> spy = spy(list);
when(spy.size()).thenReturn(100);
spy.add("one");
spy.add("two");
/* spy的原理是,如果不打樁默認都會執行真實的方法,如果打樁則返回樁實現。
可以看出spy.size()通過樁實現返回了值100,而spy.get(0)則返回了實際值*/
assertEquals(spy.get(0), "one");
assertEquals(100, spy.size());
}
註意事項:當調用方法如when().thenReturn()時,實際上還是調用了實際方法。
參考如下:
@Test
public void spy_Procession_Demo() {
Jack spyJack = spy(new Jack());
//使用spy的樁實現實際還是會調用stub的方法,只是返回了stub的值
when(spyJack.go()).thenReturn(false);
assertFalse(spyJack.go());
//不會調用stub的方法
doReturn(false).when(spyJack).go();
assertFalse(spyJack.go());
}
實現方式2-callRealMethod():
package callRealMethod;
import org.junit.Test;
import static org.mockito.Mockito.*;
public class CallMethodDemo {
@Test
public void callRealMethodTest() {
Jerry jerry = mock(Jerry.class);
doCallRealMethod().when(jerry).doSomeThingA();
doCallRealMethod().when(jerry).doSomeThingB();
jerry.goHome();
verify(jerry).doSomeThingA();
verify(jerry).doSomeThingB();
}
}
class Jerry {
public void goHome() {
doSomeThingA();
doSomeThingB();
}
// real invoke it.
public void doSomeThingB() {
System.out.println("good day");
}
// auto mock method by mockito
public void doSomeThingA() {
System.out.println("you should not see this message.");
}
}
場景3:影響範圍只在單個測試類
優點:mock對象影響範圍只在單個測試類,不影響其他測試類。
實現方式1-使用ReflectionTestUtils解決依賴註入Mock對象
@Component
public class WithdrawApplicationTest extends AccountWithdrawFacadeBaseTest {
@Captor
private ArgumentCaptor<WithdrawApplicationRequest> captor;
@Mock
private CheckPasswordComponent mockCheckPasswordComponent;
@Autowired
private CheckPasswordComponent checkPasswordComponent;
@Autowired
private AccountWithdrawWithoutLadonBiz acccountWithdrawWithoutLadonBiz;
@Autowired
private AccountWithdrawFacade withdrawFacade;
@Test
public void withdrawTest() {
WithdrawApplicationRequest applyReq = new WithdrawApplicationRequest();
applyReq.setAccountType(TYPE);
applyReq.setCustomerId(ZEUS_CUSTOMER_ID);
applyReq.setRequestPartyId(ZEUS_SOURCE_PARTY_ID);
applyReq.setSourcePartyId(ZEUS_SOURCE_PARTY_ID);
applyReq.setTransactionChannel("h5");
applyReq.setPassword(ZEUS_PASSWORD);
applyReq.setPartyTransactionId(
new Timestamp(System.currentTimeMillis()).toString());
applyReq.setPartyTransactionTime(
new Timestamp(System.currentTimeMillis()));
applyReq.setTransAmount(new BigDecimal("1000"));
applyReq.setSign(GenerateSignUtils.generateSign(applyReq,
"fd219e782ecebf0bc8f4a83e43248b45"));
given(mockCheckPasswordComponent.restCountByPassword(Mockito.anyInt(),
Mockito.anyLong(), Mockito.anyByte())).willReturn(3);
WithdrawApplicationResponse response = withdrawFacade
.withdrawApplication(applyReq);
verify(mockCheckPasswordComponent, times(1)).restCountByPassword(
Mockito.anyInt(), Mockito.anyLong(), Mockito.anyByte());
Assert.assertEquals(response.getRestAttempts(), 3);
System.err.println(JsonUtil.toFormatJson(response));
Assert.assertEquals(response.getTransactionResultDescription(), "成功");
}
@BeforeClass
private void beforeClass() {
MockitoAnnotations.initMocks(this);
try {
ReflectionTestUtils.setField(
AopTargetUtils.getTarget(acccountWithdrawWithoutLadonBiz),
"checkPasswordComponent", mockCheckPasswordComponent);
} catch (Exception e) {
logger.error("", e);
}
}
@AfterClass
public void clearMocks() throws Exception {
ReflectionTestUtils.setField(
AopTargetUtils.getTarget(acccountWithdrawWithoutLadonBiz),
"checkPasswordComponent", checkPasswordComponent);// 還原為真實bean,不影響其他case
}
}
實現方式2-官方介紹的@mock,@injectMock方式
說明:據實驗,這種模式碰到多層內嵌bean時不生效,所以暫不舉例說明,參考如下文檔。
官方文檔參考:https://static.javadoc.io/org.mockito/mockito-core/2.10.0/org/mockito/Mockito.html
場景4.mock代理類
實現方式1-通過AddtionalAnswer.delegateto(instance)
轉載:https://www.cnblogs.com/danqiu/p/7531538.html
Mockito各場景使用介紹