UT笔记:Junit 、PowerMock

来源:互联网 发布:最强的国际象棋软件 编辑:程序博客网 时间:2024/05/16 04:58
一、简介

1、Junit简介

Junit是Java单元测试框架,已经在Eclipse中默认安装。JUnit4中,测试用例直接使用@Test等注解即可。

2、使用Mock工具

有时一个方法会引用很多外部接口及其他外部对象,例如查找数据库等,但单元测试只需测试此方法的逻辑实现对错,所以需要用到mock工具来模拟这些外部依赖的对象,来完成单元测试。

3、PowerMockito简介

 PowerMock是一个功能强大的mock框架。

PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法,构造函数,final类和方法,私有方法,去除静态初始化器等等。

PowerMock很容易使用,因为对于静态方法和构造器来说,整个的期望API是一样的。PowerMock旨在用少量的方法和注解扩展现有的API来实现额外的功能。

目前PowerMock支持EasyMock和Mockit。

二、框架介绍

        整体框架示例

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.mockito.Mockito;

import org.powermock.api.mockito.PowerMockito;

import org.powermock.core.classloader.annotations.PrepareForTest;

import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)

@PrepareForTest({ServiceProxy.class,INetworkAnalysisCommonService.class})

public class TestHSRSettingQueryService {

       private IHSRSettingQueryService service;

private List<NetworkAnalysisInfo> netInfos = new ArrayList<NetworkAnalysisInfo>();

    @Before

    public void setup() {     

           setParaModel();

           mock();

           service=new HSRSettingQueryService();

    }

    private void setParaModel(){

              //自己构造的对象

NetworkAnalysisInfo a1 = new NetworkAnalysisInfo();

              a1.setRat("a-b-c");

              a1.setVendorId(1);

              a1.setVendorName("hauwei");

              netInfos.add(a1);

    }

    private void mock() {          

           PowerMockito.mockStatic(ServiceProxy.class);

           serviceProxy=PowerMockito.mock(ServiceProxy.class);

           PowerMockito.when(ServiceProxy.getInstance()).thenReturn(serviceProxy);

PowerMockito.when(networkAnalysisCommonService.queryNetworkAnalysisVendorAndNetwork()).thenReturn(netInfos);//返回自己构造的对象

    @Test

    public void testQueryTimeRangeSetting() {

           service.queryTimeRangeSetting();

    }

}

三、模块具体解析

1、  引用junit相关jar包,常见有如下七个jar:

       其中import org.powermock.modules.junit4.PowerMockRunner;

       切勿为import org.powermock.modules.junit4.legacy.PowerMockRunner;

       不然会出现如下错误:

            java.lang.NoClassDefFoundError: org/junit/internal/runners/TestClassRunner

            
         就Discovery代码,关于junit和powerMockito的jar包一般如下,包含在testbase中,如遇jar包问题,
        可通过Build Path add进去。

            

 2、两个注释

    @RunWith(PowerMockitoRunner.class),括号中是固定值,表示让测试运行于PowerMockitoRunner的测试环境下。

       @PrepareForTest( { YourClassWithEgStaticMethod.class })

         如果你的测试用例里没有使用注解@PrepareForTest,那么可以不用加注解                                                                       @RunWith(PowerMockRunner.class),反之亦然。当你需要使用PowerMock强大功能(

                Mock静态、final、final方法等)的时候,就需要加注解@PrepareForTest。

3、PowerMockito基本用法:需要进行mock的情况及@PrepareForTest中内容:

        1、  普通Mock:Mock参数传递的对象,不需要加@RunWith和@PrepareForTest注解。

        2、  Mock方法内部new出来的对象,当使用PowerMockito.whenNew方法时,必须加注解

        @PrepareForTest和@RunWith。注解@PrepareForTest里写的类是需要mock的new对象代码所在的类。

        3、  当mock类的私有方法时,和Mock普通方法一样,只是需要加注解@PrepareForTest(ClassUnderTest.class),注解里写的类是私有方法所在的类。

        4、  当需要mock 普通对象的final方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是final方法所在的类。

        5、  当需要mock普通类的静态方法的时候,必须加注解@PrepareForTest和@RunWith。注解@PrepareForTest里写的类是静态方法所在的类。

        6、  Mock系统类的静态和final方法,和Mock普通对象的静态方法、final方法一样,只不过注解@PrepareForTest里写的类不一样 ,注解里写的类是需要调用系统方法所在的类。

 

4、初始化变量

        注意全局变量和局部变量

        Mock过程中不是自己构造的mock的返回值尽量定义成局部变量

      

        自己构造的返回值可定义为全局变量

      

5、常用mock:

    读程序将调用外部接口及读取数据库等情况mock(打桩),需要返回值时需自己构造。】

        1、  Mock调用DW数据库的接口Dao:

        2、  Mock调用PT数据库的接口Dao:

        3.Res调用上层服务,Mock Res.getKey:

     

        4、Mock LicenseUtil.filterFPByLicense():

        License上层传递参数,在UT一般输入参数时自己构造的,所以调用LicenseUtil的方法时直接打桩,

    构造返回值,将LicenseUtil另行写UT。

     

        5、Mock 获取语言的方法

     

        6、PowerMockito,doNothing情况:

     

四、关于自己构造对象

   1、在给对象set具体值时要结合程序中具体调用,若程序中调用的某些属性没有进行赋值会

       出现空指针NullPointer问题。

   2、注意分支问题,当给某属性set某一具体值时,若其后有if判断,有些分支会走不到,

       为使测试覆盖率较高,要进行不同的用例测试。

    示例:

 

五、注意事项      

        1、 mock过程中调用方法有两个参数时,要保持一致,要么都为具体参数,要么都为Mockito.any类型。

    

    2、关于方法参数问题,一个比较简单通用的方法:若方法中有多个参数,

        直接写Mockito.anyObject(),然后强转成方法中需要的参数类型即可

    

   3、注意mock的顺序问题。