美文网首页Android开发经验谈Android技术知识Android开发
Android 单元测试 PowerMock框架的使用总结

Android 单元测试 PowerMock框架的使用总结

作者: 无痕_8fb8 | 来源:发表于2019-06-28 14:42 被阅读9次

    在安卓中我们常用Junit + Mockito + PowerMock 组合进行测试。PowerMock是拓展Mockito,主要是为了解决Mockito 框架不支持mock匿名类、final类、static方法、private方法的问题,PowerMock内部调用了Mockito的方法(如:PowerMockito.when()内部调用的是Mockito.when())。

    PowerMock的导入

        testImplementation "org.powermock:powermock-module-junit4:1.7.3"
        testImplementation "org.powermock:powermock-module-junit4-rule:1.7.3"
        testImplementation "org.powermock:powermock-api-mockito2:1.7.3" //注意这里是mockito2
        testImplementation "org.powermock:powermock-classloading-xstream:1.7.3"
    

    PowerMock使用

    首先我们定义一个Fruit类,Banana继承于它。其中有我们后面需要mock的static、private等方法。

    abstract class Fruit {
    
        private String fruit = "水果";
    
        public String getFruit() {
            return fruit;
        }
    }
    
    public class Banana extends Fruit {
    
        private static String COLOR = "黄色的";
        private static String SIZE = "BIG";
        private String place = "here";
    
        public Banana() {}
    
        public String getPlace() {
            return place;
        }
    
        public static final String getColor() {
            return COLOR;
        }
    
        private static String getSize() {
            return SIZE;
        }
    
        public String getBananaInfo() {
            return flavor() + getColor();
        }
    
        private String flavor() {
            return "甜甜的";
        }
    
        public final boolean isLike() {
            return true;
        }
    
        private final String getPrice() {
            return "10";
        }
    
        public String privateFinal() {
            return getPrice();
        }
    }
    
    定义Mock类,:

    方法一:

    @RunWith(PowerMockRunner.class)
    @PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
    public class PowerMockito {
        @Test
        @PrepareForTest({Banana.class})
        public void testMethod() throws Exception {
    
        }
    }
    

    首先使用PowerMock必须在类名上加注@RunWith(PowerMockRunner.class),在方法上添加注解@PrepareForTest,注解@PrepareForTest里写的是要mock的方法所在的类。@PowerMockIgnore用于忽略mock的类,"android.*" 忽略android的相关类,因为我们使用Robolectric处理了;"org.mockito.*""org.robolectric.*" 忽略Mockito和Robolectric的相关类,因为我们不应该mock它们自己。

    方法二:
    有时我们会使用多个测试框架,可能@RunWith会占用,这时我们可以使用@Rule

    @PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
    public class PowerMockito {
         @Rule
         public PowerMockRule rule = new PowerMockRule();
    
        @Test
        @PrepareForTest({Banana.class})
        public void testMethod() throws Exception {
    
        }
    }
    
    使用方法总结,(final)表示final可有可无:

    1、Mock public (final):

    @Test
    @PrepareForTest({Banana.class})
    public void testMethod() throws Exception {
        Banana mBanana = PowerMockito.mock(Banana.class);
        PowerMockito.when(mBanana.isLike()).thenReturn(false);
        Assert.assertFalse(mBanana.isLike());
    }
    

    2、Mock public static (final):

    @Test
    @PrepareForTest({Banana.class})
    public void testMethod() throws Exception {
        PowerMockito.mockStatic(Banana.class);
        PowerMockito.when(Banana.getColor()).thenReturn("green");
        Assert.assertEquals("green", Banana.getColor());
    }
    

    3、Mock private (final):

    @Test
    @PrepareForTest({Banana.class})
    public void testMethod() throws Exception {
        Banana banana = PowerMockito.mock(Banana.class);
        PowerMockito.when(banana.getBananaInfo()).thenCallRealMethod();
        PowerMockito.when(banana, "flavor").thenReturn("苦苦的");
        Assert.assertEquals("苦苦的黄色的", banana.getBananaInfo());
    }
    

    4、Mock private static (final): 无法模拟

    5、更改类的私有static常量,不能是final:

    @Test
    @PrepareForTest({Banana.class})
    public void testMethod() throws Exception {
        Whitebox.setInternalState(Banana.class, "COLOR", "red");
        Assert.assertEquals("red", Banana.getColor());
    }
    
    

    6、跳过私有方法:

    @Test
    @PrepareForTest({Banana.class})
    public void testMethod() throws Exception {
        PowerMockito.suppress(PowerMockito.method(Banana.class, "flavor"));
        Assert.assertEquals("null黄色的", mBanana.getBananaInfo());
    }
    

    7、更改父类私有变量,不能是final:

    @Test
    @PrepareForTest({Banana.class})
    public void testMethod() throws Exception {
        Banana mBanana = new Banana();
        MemberModifier.field(Banana.class, "fruit").set(mBanana, "蔬菜");
        Assert.assertEquals("蔬菜", mBanana.getFruit());
    }
    

    8、Mock 构造方法:

    @Test
    @PrepareForTest({Banana.class})
    public void testMethod() throws Exception {
        Banana mBanana = PowerMockito.mock(Banana.class);
        PowerMockito.when(mBanana.getBananaInfo()).thenReturn("大香蕉");
    
        //如果new新对象,则返回这个上面设置的这个对象    
        PowerMockito.whenNew(Banana.class).withNoArguments().thenReturn(mBanana);
        //new新的对象
        Banana newBanana = new Banana();
        Assert.assertEquals("大香蕉", newBanana.getBananaInfo());
    }  
    

    参考文章:
    Android单元测试(三):PowerMock框架的使用

    相关文章

      网友评论

        本文标题:Android 单元测试 PowerMock框架的使用总结

        本文链接:https://www.haomeiwen.com/subject/kszkxctx.html