powermockito测试私有方法_SpringBoot使用Powermockito mock静态方法/私有方法 第342篇

472dc23bcd9be967203d4b980aa8723a.gif

f6675782f230d31218afb065d78f6dbe.png

关历史文章(阅读本文前,您可能需要先看下之前的系列?)

国内最全的Spring Boot系列之三

2020上半年发文汇总「值得收藏」

SpringBoot框架开发的优秀的项目「值得收藏学习」 - 第335

Mock工具之Mockito - 第337篇

Spring Boot中使用Mockito - 第338篇

Spring Boot中使用Mockito进行Web测试 - 第339篇

Mockito中捕获mock对象方法的调用参数[SpringBoot]

SpringBoot使用Mockito mock静态方法/私有方法 - 第341篇

悟纤:师傅,我最近发现一个家伙,特别厉害。

e211d63ea340122e300a5cd255606b68.gif

师傅:是不是发现了新大陆了。

悟纤:嗯,我最近看到一个更牛逼的家伙Poowermockito增强了mockito的能力。

师傅:那徒儿和为师分享一下你学习的心得呗。

悟纤:那徒儿就献丑了。

一、Mockito和PowerMock的简介

Mocktio和PowerMock都是Mock的工具类,主要是Java的类库,Mock就是伪装的意思。他们适用于单元测试中,对于单元测试来说,我们不希望依赖于第三方的组件,比如数据库、Webservice等。在写单元测试的时候,我们如果遇到了这些需要依赖第三方的情况,我们可以使用mock的技术,伪造出来我们自己想要的结果。对于Java而言,mock的对象主要是Java 方法和Java类。

二、Mockito和PowerMock的区别

PowerMock是Mockito的一种增强,PowerMock可以调用Mockito的方法,但是对于Mocktio不能Mock的对象或者方法,我们可以使用PowerMock来实现。比如Mockito不能用于static Method, final method, 枚举类, private method,这些我们都可以用powermock来实现,当然对于新版的Mockito配合上mockito-inline能解决部分的问题,这个具体看前面的章节《SpringBoot使用Mockito mock静态方法/私有方法》。

二、Mockito和PowerMock版本对应关系

Mockito

PowerMock

2.8.9+

2.x

2.8.0-2.8.9

1.7.x

2.7.5

1.7.0RC4

2.4.0

1.7.0RC2

2.0.0-beta -  2.0.42-beta

1.6.5-1.7.0RC

1.10.8 - 1.10.x

1.6.2 - 2.0

1.9.5-rc1 - 1.9.5

1.5.0 - 1.5.6

1.9.0-rc1 & 1.9.0

1.4.10 - 1.4.12

1.8.5

1.3.9 - 1.4.9

1.8.4

1.3.7 & 1.3.8

1.8.3

1.3.6

1.8.1 & 1.8.2

1.3.5

1.8

1.3

1.7

1.2.5

三、PowerMock的使用

3.1 单元测试类上的注解说明

在 Spring Boot 的测试套件中,需要添加@RunWith(SpringRunner.class) 和 @SpringBootTest 注解。

但是 PowerMock 需要添加@RunWith(PowerMockRunner.class) 注解。@RunWith 注解只能有一个,解决方案是使用 @PowerMockRunnerDelegate 注解,同时使用@PowerMockIgnore 注解避免报错:

/** * * @author 悟纤「公众号SpringBoot」 * @date 2020-12-28 * @slogan 大道至简 悟在天成 */@SpringBootTest@RunWith(PowerMockRunner.class)@PowerMockRunnerDelegate(SpringRunner.class)@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})// 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类@PrepareForTest({UserController.class})public class TestStaticMethod {}

3.2 mock静态方法

       静态代码的编写和前面章节的《SpringBoot使用Mockito mock静态方法/私有方法》是一样的,这里不重复编写了,主要来看下具体的mock代码编写的区别:

@Beforepublic void setUp() {    PowerMockito.mockStatic(UserController.class);    PowerMockito.when(UserController.isTrue(any(String.class))).thenReturn(true);}/** * mock静态方法 */@Testpublic void verifyStaticMock() {    boolean flag = userController.verifyStaticMcok("");    Assert.assertTrue(flag);}

3.3 mock私有方法

       我能在UserController添加一个私有方法:

/** * mock私有方法 * * @param userName 用户名 */@GetMapping(value = "/verifyPrivateMethod")public String verifyPrivateMethod(String userName) {    System.out.println("传入的用户名:" + userName);    String result = getUserName(userName);    return result;}/** * 私有方法 * * @param str 传入参数 */private String getUserName(String str) {    System.out.println("进入了私有方法" + str);    return str;}

       看下我们的mock代码:

/** * mock私有方法 */@Testpublic void verifyPrivateMethod() throws Exception {    //spy 方法可以包装一个真实的 Java 对象, 并返回一个包装后的新对象    // spy被测类,只有被spy出来的类,才可以对私有方法进行mock    UserController spy = PowerMockito.spy(userController);    // 模拟私有方法(反射),意思是传入"zhangsan",强制返回"lisi"    PowerMockito.when(spy, "getUserName", "zhangsan").thenReturn("lisi");    String userName = spy.verifyPrivateMethod("zhangsan");    // 验证私有方法被执行了    PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke("getUserName", "zhangsan");    Assert.assertEquals("lisi", userName);}

       最后提供一下整个测试类:

package com.kfit.springbootmockitodemo;import com.kfit.springbootmockitodemo.demo.controller.UserController;import org.junit.Assert;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.PowerMockIgnore;import org.powermock.core.classloader.annotations.PrepareForTest;import org.powermock.modules.junit4.PowerMockRunner;import org.powermock.modules.junit4.PowerMockRunnerDelegate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import static  org.mockito.Mockito.*;/** * * @author 悟纤「公众号SpringBoot」 * @date 2020-12-28 * @slogan 大道至简 悟在天成 */@SpringBootTest@RunWith(PowerMockRunner.class)@PowerMockRunnerDelegate(SpringRunner.class)@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})// 所有需要测试的类列在此处,适用于模拟final类或有final, private, static, native方法的类@PrepareForTest({UserController.class})public class TestStaticMethod {    @Autowired    private UserController userController;    /**     * 测试启动前,首先 mock 出静态方法     */    @Before    public void setUp() {        PowerMockito.mockStatic(UserController.class);        PowerMockito.when(UserController.isTrue(any(String.class))).thenReturn(true);    }    /**     * mock静态方法     */    @Test    public void verifyStaticMock() {        boolean flag = userController.verifyStaticMcok("");        Assert.assertTrue(flag);    }    /**     * mock私有方法     */    @Test    public void verifyPrivateMethod() throws Exception {        //spy 方法可以包装一个真实的 Java 对象, 并返回一个包装后的新对象        // spy被测类,只有被spy出来的类,才可以对私有方法进行mock        UserController spy = PowerMockito.spy(userController);        // 模拟私有方法(反射),意思是传入"zhangsan",强制返回"lisi"        PowerMockito.when(spy, "getUserName", "zhangsan").thenReturn("lisi");        String userName = spy.verifyPrivateMethod("zhangsan");        // 验证私有方法被执行了        PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke("getUserName", "zhangsan");        Assert.assertEquals("lisi", userName);    }}

四、总结

       为什么mockito不能mock静态方法(mockito-inline为什么可以呢)?mockito使用继承的方式实现mock的,用CGLIB生成mock对象代替真实的对象进行执行,为了mock实例的方法,你可以在子类中覆盖它,而static方法是不能被子类覆盖的,所以mockito不能mock静态方法。但powermock可以mock静态方法,因为它直接在字节码上工作。

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

à悟空学院:https://t.cn/Rg3fKJD

学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!

SpringBoot视频:http://t.cn/A6ZagYTi

SpringBoot交流平台:https://t.cn/R3QDhU0

SpringSecurity5.0视频:http://t.cn/A6ZadMBe

ShardingJDBC分库分表:http://t.cn/A6ZarrqS

分布式事务解决方案:http://t.cn/A6ZaBnIr

JVM内存模型调优实战:http://t.cn/A6wWMVqG

Spring入门到精通:https://t.cn/A6bFcDh4

大话设计模式之爱你:https://dwz.cn/wqO0MAy7

33b34fae1efd56863f7fa0e53a2044e1.gif

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值