PowerMock处理特殊的单元测试

来源:互联网 发布:哑铃品牌知乎 编辑:程序博客网 时间:2024/06/04 18:56

背景

代码设计并不总是尽善尽美,有些单元测试是Mockito力不从心的。
这时候就需要PowerMock ,这个框架是对Mockito增强。
下面展示几个常用场景
- mock静态方法
- 跳过私有方法
- 更改子类无法访问的父类私有field
- 更改类的私有static常量
- 模拟New构造函数

示例

首先引入Maven依赖

        <dependency>            <groupId>org.powermock</groupId>            <artifactId>powermock-api-mockito</artifactId>            <version>1.7.0</version>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.powermock</groupId>            <artifactId>powermock-module-junit4</artifactId>            <version>1.7.0</version>            <scope>test</scope>        </dependency>

要测试的业务类包含了几个特殊用例

abstract class MyParent {    private String parentValue = "parent";    private String getMessageContent() {        return parentValue;    }    protected String getParentMessage() {        return getMessageContent();    }}public class Mytest extends MyParent {    private static String BID = "999";    public Mytest() {    }    public static String getBid() {        return BID;    }    public static String getMessage() {        return "hello";    }    public String sendEmail() {        String response = "send email";        System.out.println(response);        response = sendMessage("success");        return response;    }    private String sendMessage(String status) {        System.out.println("send message " + status);        return "send message " + status;    }}

编写单元测试

import org.junit.Assert;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mockito;import org.powermock.api.mockito.PowerMockito;import org.powermock.api.support.membermodification.MemberModifier;import org.powermock.core.classloader.annotations.PrepareForTest;import org.powermock.modules.junit4.PowerMockRunner;import org.powermock.reflect.Whitebox;@RunWith(PowerMockRunner.class) //以PowerMock启动Junit test@PrepareForTest({Mytest.class}) //预处理要mock的类,在字节码的级别更改类的行为public class Testmethod {    @Test    public void testStaticMethod() {//mock静态方法        PowerMockito.mockStatic(Mytest.class);        Mockito.when(Mytest.getMessage()).thenReturn("world");        Assert.assertEquals("world", Mytest.getMessage());    }    @Test    public void skipPrivateMethod() {//跳过私有方法        Mytest t = new Mytest();        PowerMockito.suppress(PowerMockito.method(Mytest.class, "sendMessage", String.class));  //类,方法名,参数类        String response = t.sendEmail();        Assert.assertTrue(response == null);//跳过了sendMessage方法,返回为null    }    @Test    public void changeParentPrivate() {//更改子类无法访问的父类私有field        Mytest t = new Mytest();        try {            MemberModifier.field(Mytest.class, "parentValue").set(                    t, "tomcat");        } catch (IllegalAccessException e) {            e.printStackTrace();        }        Assert.assertEquals("tomcat", t.getParentMessage());//父类私有field已经被更改    }    @Test    public void changeBid() {//更改类的私有static常量        Whitebox.setInternalState(Mytest.class, "BID", "888");        Assert.assertEquals("888", Mytest.getBid());    }    @Test    public void mockNew() throws Exception {//模拟New构造方法        Mytest test = Mockito.mock(Mytest.class);        Mockito.when(test.getParentMessage()).thenReturn("hello");        PowerMockito.whenNew(Mytest.class).withNoArguments().thenReturn(test);        Mytest testNew = new Mytest();        Assert.assertEquals("hello", testNew.getParentMessage());    }}

已知问题

PowerMock实现了自己的类加载器,占用内存大,容易造成内存不足:OutOfMemoryError

阅读全文
0 0