Mockito各场景使用介绍

摘要:
--ID必须与biz中autowired的属性值一致,然后@Resource测试类中的对象,并存根对象的方法以指定返回数据--˃˂!如果一个方法定制了返回值或异常,那么它将以定制的方式被调用和执行;如果一个方法不是定制的,它将调用实际类的方法。如果我们想在定制方法A之后在下一个测试方法中调用real方法,我们只需要在调用方法A之前调用Mockito.reset。可以看出那个间谍。size()通过stake实现返回值100,而s

场景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 classWithdrawConfiguration {

    @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 classCallMethodDemo {

    @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();  

    }  

}

 

classJerry {  

    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 classWithdrawApplicationTestextendsAccountWithdrawFacadeBaseTest {

    @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)

 

Mockito各场景使用介绍第1张

 

 

 

 

免责声明:文章转载自《Mockito各场景使用介绍》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇UI自动化学习之坑React项目创建下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

spring装配bean的三种方式及其混合装配

在spring容器中装配bean有三种基本方式和混合装配方式: 隐式的bean自动发现机制和自动装配 在java中进行显式配置 在xml中配置 混合装配(在多个java文件中配置、在JavaConfig中引用XML配置、在XML中引用JavaConfig配置) 一、使用自动化方式装配bean示例: 1:创建maven项目并引入依赖: <?xml...

深入Android渲染机制

1.知识储备 CPU: 中央处理器,它集成了运算,缓冲,控制等单元,包括绘图功能.CPU将对象处理为多维图形,纹理(Bitmaps、Drawables等都是一起打包到统一的纹理). GPU:一个类似于CPU的专门用来处理Graphics的处理器, 作用用来帮助加快格栅化操作,当然,也有相应的缓存数据(例如缓存已经光栅化过的bitmap等)机制。 Open...

Spring-session redis 子域名 session

Spring-session & redis 子域名共享session 例子: a.example.comb.example.comSpring 版本 4.2.6.RELEASE Spring-session Maven 依赖相关的包 <!-- redis --> <dependency> <groupId>re...

窗口分析

(本文尝试通过一些简单的实验,来分析Windows的窗口机制,并对微软的设计理由进行一定的猜测,需要读者具备C++、Windows编程及MFC经验,还得有一定动手能力。文中可能出现一些术语不统一的现象,比如“子窗口”,有时候我写作“child window”,有时候写作“child”,我想应该不会有太大影响,文章太长,不一一更正了) 问题开始于我的最近的一...

eclipse+maven+ssm框架搭建

eclipse+maven+ssm框架 0、系统环境 1)Windows 10 企业版 2)JDK 1.8.0_131 3)Eclipse Java EE IDE for Web Developers  Version: Neon.3 Release (4.6.3) 4)Tomcat 8.5 1、maven下载及配置 maven的下载地址:http:...

@Value("#{}")与@Value("${}")的区别以及用法

1 packagecom.ieou.capsule_basic_info.util; 2 3 4 importorg.springframework.beans.factory.annotation.Value; 5 importorg.springframework.stereotype.Component; 6 importorg.spr...