1. 程式人生 > >Mockito各場景使用介紹

Mockito各場景使用介紹

rec 調用方法 wire mount sig 測試 app something fail

場景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

  1. 部分mock解釋說明:部分mock是說一個類的方法有些是實際調用,有些是使用mockito的stubbing(樁實現)
  2. mockito實現部分mock的兩種方式:spy和callRealMethod()
  3. Spy類就可以滿足我們的要求。如果一個方法定制了返回值或者異常,那麽就會按照定制的方式被調用執行;如果一個方法沒被定制,那麽調用的就是真實類的方法。
  4. 如果我們定制了一個方法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各場景使用介紹