zoukankan      html  css  js  c++  java
  • 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

    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)

     

     

     

     

     

  • 相关阅读:
    MySQL关键性能监控(QPS/TPS)
    Python小技巧
    Redis高可用演进(一)
    防范XSS攻击
    java引用知识
    ehcache同步原理
    ehcache监控
    SecureCRT使用技巧
    JUC整理笔记五之梳理Varhandle(下)
    JUC整理笔记四之梳理VarHandle(上)
  • 原文地址:https://www.cnblogs.com/danqiu/p/7531538.html
Copyright © 2011-2022 走看看