温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

junit单体测试(PowerMockito)一

发布时间:2020-06-13 10:41:17 来源:网络 阅读:7134 作者:骑猴上树 栏目:软件技术

    最近刚刚离职,离职前1个月项目尾声,在公司做单体测试,从模仿开始,积累了一些东西,记录下来,留备以后不时之需;在做的时候我也在谷歌之类的搜索想深入学习下,有个感悟就是国内的相关书籍都是比较旧的,一般都是04年左右的东西,和现在做的关联性不大,可能看看也有点用,原理应该是相同的,但是没有实例,没有和所用的技术相一致的api,感觉很浪费时间,谷歌上的api和stackoverflow上的提问之类的都是比较靠谱和比较贴近工作的,但又全是英语的,有一些大致能看懂,但是抠细节就不够用了,下边是工作中遇到的一些问题,自己做的总结,可能以后某一天还会做单体测试,也可以快速捡起来。

    需要jar包:

    javassist-3.16.1-GA.jar

    mockito-all-1.9.5.jar

    powermock-api-mockito-1.5.6.jar

    powermock-api-support-1.5.6.jar

    powermock-core-1.5.6.jar

    powermock-module-junit4-1.5.6.jar

    powermock-module-junit4-common-1.5.6.jar

    powermock-reflect-1.5.6.jar

    junit-4.10.jar

    在使用mock时,首先要在测试类上加上注解@PrepareForTest({类名.class}),这里的“类名.class”是类里调用的类,需要被mock的类

  1. 当需要mock私有方法调用的私有方法时,需要加上@RunWith(PowerMockRunner.class),其余不需要加,创建时也可以用new。

  2. public调用有返回值的private方法

    PowerMockito.when(对象,“私有方法名”,参数).thenReturn(期望的value);此方法要加上@RunWith(PowerMockRunner.class),此时创建类的对象时不能直接用new,需要用PowerMockito.Mock(类名.class);并需要将 类名.class放到类上的注解@PrepareForTest({类名.class})内;

  3. 用mock对象替换原代码中的对象

    e.g:

    public class AA{

    Private User u;

    public void A(){

         u.getName();    

    }

    }

    @PrepareForTest({User.class})

    Public class test{

        @Test

        public void test_001(){

            AA a = new AA();

            User u1 = PowerMockito.Mock(User.class);

            Whitebox.setInternalState(a,"u",u1);

            PowerMockito.when(u1.getName()).thenReturn(value);

        }

        

    }

 4.要对一个类内,方法调用的方法进行mock

   e.g:public class AA{

        private User u;

        private Ver v;

        public void getData(){

            String a = u.getName();

            String b = v.getAge();

        }

   }

   测试的过程:①.首先对整个类进行mock

               ②.然后调用方法

               ③.接着mock调用的类

               ④.新对象的名字代替代码里的

               ⑤.对方法进行mock 

               ⑥.调方法。 

   e.g:①.AA a = PowerMockito.mock(AA.class);

       ②.PowerMockito.doCallRealMethod.when(a).getData();

       ③.User u1 = PowerMockito.mock(User.class);

       ④.Whitebox.setInternalState(a,"u",u1);   

       ⑤.PowerMockito.when(u1.getName()).thenReturn(value);

       ⑥.a.getData();

5.测试中测异常

PowerMockito.doThrow(new Exception()).when(对象).getName();

new Exception()是你期待的异常,getName是出异常的方法;

6.测试异常实例

e.g:public class A{

    private U u = null;

    public void putData(Data d){

        try{

            u.putData(参数,参数);

        }catch(AccessException e){

            throw new xxxxException(e,....);

        }

}

}


测试类

@prepareForTest{(A.class,U.class)}

public class ATest{

    @Test

    public void test_001(){    

    Data d = new Data();

    d.setName("a");

    A a = PowerMockito.mock(A.class);

    PowerMockito.docallRealMethod.when(a).putData(d);

    U u = PowerMockito.mock(U.class);

    whitebox.setInteralState(a,"u",u);

    try{

        PowerMockito.doThrow(new AccessException()).when(u).putData(Mockito.any(...class),Mockito.any(..class));

        a.putData(d);

    }catch(AccessException e){

        assertTrue(e instaceof xxxException);

        assertEquals(e.getException.getMessage(),"xxxxxxx");

    }

    }    

}

mock public 方法里调用的私有方法

A a = PowerMockito.mock(A.class);

PowerMockito.doCallRealMethod().when(a).putData(); //putData()为A的方法

PowerMockito.when(a,"getName()",value.getId(),value.getName()).thenReturn("abc");// getName为私有方法,value.getId(),value.getName()为方法参数

参数要看代码中是用的什么,如果代码中是value.getId()的形式,测试代码中也要是这种形式,否则就会无法返回期望值。


7、在对方法进行mock时,要注意写法一致

错误写法:

PowerMockito.doReturn(xx).when(instance,method(args));

①、PowerMockito.doReturn(xx).when(instance).方法名(args);

②、PowerMockito.when(instance.方法名(args));.thenReturn(xx);

在mock时,方法的参数优势会遇到问题(造不出来),可使用Mockito.any()和mockito.eq()来解决;

e.g:Mockito.any(User.class) //参数是对象,可以用any,里面为类.class;

    Mockito.eq(字段名);//参数是字符串等类型; 用eq


8、在对方法进行mock时,方法里使用的全局成员变量始终为null(事实上在成员变量初始化时,是设置初始值了的,但是却为null),要给成员变量在case里赋值。

使用Whitebox.setInternalState(instance,"代码里字段名",新名字);

可以在上边为新名字赋上值传进去。


9、在A类的B方法里有对同一个类的私有方法C的调用,并需要返回值。(此方法堪称大招,对测试私有方法,并mock私有方法内的私有方法有奇效!!!)

public void test_001(){

    A a = PowerMockito.mock(A.class);

    PowerMockito.when(a,"c",arg1,arg2).thenReturn("01");

    Whitebox.invokeMethod(a,"c",arg1,arg2); //c是私有方法名

    PowerMockito.when(a,"B",args).thencallRealMethod();

    Whitebox.invokeMethod(a,"B",args);

}


10、mock A类的构造器(有时构造器可能有很复杂的处理),但需要造一个假的对象来使用

@RunWith(PowerMockRunner.class)

@PrepareForTest({A.class,B.class})

public class BTest{

    @Test

    public void test_001(){

        B b = PowerMockito.Mock(B.class);

        PowerMockito.doCallRealMethod().when(b).getName(id);

        A a = PowerMockito.mock(A.class);

        PowerMockito.whenNew(A.class).withArguments(Mockito.any(C.class),Mockito.any(D.class)).thenReturn(a);

    }

}


11、在A类的B方法里new了C类(局部的),并用C对象调用了C类的方法。

mock局部对象的方法:

    A a = new A();

    C c = new C();

    PowerMockito.whenNew(C.class).whthArguments().thenReturn(c);

    c.getName();


12.mock 静态方法

@RunWith(PowerMockRunner.class)

@PrepareForTest({A.class})

public class ATest{

    @Test

    public void test_static_001(){

        PowerMockito.mockStatic(A.class);

        PowerMockito.when(A.getName()).thenReturn("01");

    }

}


13.mock 全局变量的方法2

public class A{

    private User u ;

}

使用Powermockito.field(xx.class,"字段").set(对象,想赋的值);


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI