PowerMock(一):PowerMock的基本使用

2023-10-30

文章目录

    为啥要使用PowerMock
    PowerMock的使用
        环境
        引入依赖
        注解说明
        mock普通方法
        mock抛出异常
        mock新建对象
        mock无返回值的方法
        mock被final修饰的方法
        参数模糊匹配
        mock静态方法
        mock私有方法
        总结
        参考

为啥要使用PowerMock

现在流行的测试驱动开发TDD(Test-Driven Development) ,是敏捷开发中一项核心实践和技术。也是一种设计方法论。其中最重要的一环就是使用单元测试。
单元测试是保证代码质量的一个重要手段,通过单元测试我们可以快速的测试代码的各个分支,各种场景,代码重构时只需要重新跑下单元测试就是能知道代码潜在的问题。
单元测试是通过Mock的方式调用被测试的方法,其有如下几个优点:

    Mock可以解除测试对象对外部服务的依赖(比如数据库,第三方接口等),使得测试用例可以独立运行。不管是单体应用还是微服务,这点都特别重要。
    Mock的第二个好处就是替换外部服务调用,提升测试用例的运行速度。因为任何外部服务调用至少是跨进程级别的消耗,甚至是跨系统、跨网络的消耗,而Mock可以把消耗降低到进程内。
    Mock的第三个好处就是提升测试效率,提高单位时间内测试的接口数量。
    Mock的框架有很多中比如EasyMock等,这里选用PowerMock是因为PowerMock可以用来Mock 私有方法,静态方法以及final方法。EasyMock等则不能。

PowerMock的使用
环境
软件    版本
junit    4.13
powermock    2.0.7
引入依赖

  <properties>
        <powermock.version>2.0.7</powermock.version>
    </properties>
     <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <!--powermock开始-->
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito2</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <!--powermock结束-->


这里引入了是三个依赖,junit依赖如果项目中已有的话,则不需要重复引入,需要注意的是JUnit 4.4及以上版本的JUnit需要引入2.0.x 版本以上的 powermock 。如果项目中有mockito依赖还需要注意mockito的版本与powermock版本对应关系,对应如下图:
详细请参考Using PowerMock with Mockito,如果引入的版本不匹配则可能会报如下错误:

java.lang.TypeNotPresentException: Type org.powermock.modules.junit4.PowerMockRunner not present



依赖引入之后就可以编写单元测试代码了。
注解说明

现有一个待测试的类UserServiceImpl,该类中注入了一个UserMapper的类实例。

@Service
public class UserServiceImpl {
     @Autowried
    private UserMapper userMapper;
    ........省略部分方法
}


那么如何对上面的类通过powermock的方式进行单元测试呢?首先是定义一个测试类,定义如下:

@RunWith(PowerMockRunner.class)
@PrepareForTest({UserServiceImpl.class, DateUtil.class, UserMapper.class})
public class UserServiceImplTest {
      @Mock
    private UserMapper userMapper;
    @InjectMocks
    private UserServiceImpl userServiceImpl = new UserServiceImpl();
}



@RunWith(PowerMockRunner.class) 注解表明使用PowerMockRunner运行测试用例,这个必须添加,不然无法使用PowerMock。
@PrepareForTest({UserServiceImpl.class, DateUtil.class, UserMapper.class}) @PrepareForTest 注解是用来添加所有需要测试的类,这里列举了三个需要测试的类。
@Mock注解修饰会mock出来一个对象,这里mock出来的是UserMapper类实例。
@InjectMocks 注解会主动将已存在的mock对象注入到bean中,按名称注入,这个注解修饰在我们需要测试的类上。必须要手动new一个实例,不然单元测试会有问题。
这几个注解是一个测试类必须要的。说完了测试类的定义,接下来就让我们来看看各种方法是如何mock的。
mock普通方法

    待测试的方法(UserMapper中)

 boolean saveUser(User user) {
        int i = userMapper.addUser(user);
        return i == 1 ? true : false;
    }



这里的方法int i = userMapper.addUser(user); 有入参,有出参,没有关键字修饰,是一个普通的方法,mock的方式也很简单,就是PowerMockito.when(userMapper.addUser(user)).thenReturn(1); 在when方法中调用你需要mock的方法,thenReturn方法写入你期待返回的值。从字面意思理解就是当调用xxx方法时,返回xxx值。 详细的示例如下:
2. 测试方法

 User user = new User();
        user.setId(1);
        user.setUserName("test");
        user.setPassword("admin123");
        PowerMockito.when(userMapper.addUser(user)).thenReturn(1);
        boolean result = userServiceImpl.saveUser(user);
        Assert.assertEquals(true, result);



mock抛出异常

单元测试中我们有时候需要mock异常的抛出,其mock的方式也很简单就是在thenThrow(new Exception())写入你期待抛出的异常。如果被mock的方法抛出的是受检异常(checked exception)的话,那么thenThrow抛出new Exception()或者其子类。
如果被mock的方法抛出的是非受检异常(unchecked exception),那么thenThrow抛出new RuntimeException或其子类。使用的示范如下:

    待测试的方法(UserMapper中)

 int delUser(int id) throws Exception {
        if (id == -1) {
            throw new Exception("传入的id值不对");
        } else {
            return 1;
        }
    }



    测试方法

   PowerMockito.when(userMapper.delUser(-1)).thenThrow(new Exception());


这里delUser方法抛出的是受检异常Exception,所以在thenThrow中需要new一个Exception对象。
mock新建对象

如果我们要对一个实体对象Bean进行Mock,只需要这样写PowerMockito.whenNew(User.class).withAnyArguments().thenReturn(user)
这个代码的意思是创建一个User实例对象,不管传入啥参数都返回定义的实例user,用于替换被测试方法中相应的User对象。使用示范如下:

    待测试的方法(UserMapper中)

 public int countUser() {
        User user = new User();
        int count = 0;
        if (user.getId() > 0) {
            count += 1;
        }
        return count;
    }



    测试方法

 // 6.mock新建对象
        User user = new User();
        user.setId(11);
        PowerMockito.whenNew(User.class).withAnyArguments().thenReturn(user);
        int result = userServiceImpl.countUser();
        Assert.assertEquals(1, result);



这里mock了一个User对象。id是11,当调用countUser方法时可以拿到之前mock的User对象,所以返回的结果是1。
mock无返回值的方法

对于返回值是通过void修饰的方法,他的mock方式与普通方法的mock方式不同。有两种方式mock。
方式一:

  PowerMockito.doNothing().when(userMapper, "updateUser", new User());



在when方法中传入userMapper类实例,需要调用的方法名,以及需要传入的参数。
方式二:

  PowerMockito.doNothing().when(userMapper).updateUser(user);


在when方法中只传入userMapper类实例,然后通过函数式调用的方式调用待测试的方法。
使用示范如下:

    待测试的方法(UserServiceImpl中)

 public void updateUser(User user) {
        userMapper.updateUser(user);
    }

    测试方法

  User user = new User();
        // 4.mock返回值为void的方法
        //方法一
        PowerMockito.doNothing().when(userMapper, "updateUser", new User());
        //方法二
        PowerMockito.doNothing().when(userMapper).updateUser(user);
        userServiceImpl.updateUser(user);



mock被final修饰的方法

现在有一个方法被final关键字修饰,那么该如何要mock这个方法,首先需要mock出一个类实例。如下所示:

    UserMapper mock = PowerMockito.mock(UserMapper.class);

这里需要特别注意的是被mock的类必须要在@PrepareForTest注解中指定,如本例中的@PrepareForTest({UserMapper.class})。不然就会报如下错误:

org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.

使用示范如下:

    待测试的方法(UserMapper中)

    final String getUserName() {
        return "admin";
    }


    测试方法

  UserMapper mock = PowerMockito.mock(UserMapper.class);
  when(mock.getUserName()).thenReturn("123");


参数模糊匹配

前面的测试方法中,参数我们都是指定的,在一些场景下,对于一些比较复杂的参数,我们不好构造,这时候参数模糊匹配就派上用场了。如下所示,现有方法selectUser,他有三个参数,参数类型个不相同。

User selectUser(Integer id, String userName, String password)



当对这个方法进行mock时,可以不用传入具体的参数值。就行这样进行mock。

PowerMockito.when(userMapper.selectUser(ArgumentMatchers.anyInt(), ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(user);


。。。。。。。。。。。。。。。。。

版权原因,完整文章,请参考如下:

PowerMock(一):PowerMock的基本使用
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PowerMock(一):PowerMock的基本使用 的相关文章

  • Java 中等效的并行扩展

    我在 Net 开发中使用并行扩展有一些经验 但我正在考虑在 Java 中做一些工作 这些工作将受益于易于使用的并行库 JVM 是否提供任何与并行扩展类似的工具 您应该熟悉java util concurrent http java sun
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • Final字段的线程安全

    假设我有一个 JavaBeanUser这是从另一个线程更新的 如下所示 public class A private final User user public A User user this user user public void
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview

随机推荐

  • 替代notepad++最优选择之一:vscode

    notepad 作者作妖不是一次两次了 实际上我的一些体制内或者有要求的大公司的朋友 都又在要求替换notepad 我之前没有选择替换notepad 主要是习惯了其操作方式和插件化 很多同类的工具一般有以下三类毛病 1 收费 2 功能少 不
  • 钉钉桌面版(dingtalk)介绍:支持Linux、Windows和macOS平台

    钉钉桌面版 dingtalk 介绍 支持Linux Windows和macOS平台 钉钉桌面版 dingtalk 它基于electron及钉钉网页版开发的跨平台桌面版钉钉 支持Linux Windows和macOS平台 以下是关于钉钉桌面版
  • Flutter网络请求与JSON解析

    本文介绍如何在Flutter中创建HTTP网络请求和对请求的json string进行类型解析 网络请求 官方使用的是用dart io中的HttpClient发起的请求 但HttpClient本身功能较弱 很多常用功能都不支持 建议使用di
  • 深度学习框架选择

    介绍 开源已经成为一种深度学习框架能否流行的唯一途径 如果你有需要 上GitHub就可以找到他们的源码和文档 深度学习框架比较 Keras 受到 Torch 启发 Keras 提供了简单易用的 API 接口 特别适合初学者入门 其后端采用
  • docker --help 命令

    Usage docker COMMAND A self sufficient runtime for containers Options config string Location of client config files defa
  • 系统安装部署系列教程(一):安装原版系统镜像

    电脑在使用过程中难免遇到问题 其中最万能 并不是一定有用 的一种方法就是重装系统了 很多人都不会安装系统 有时候甚至需要付费让别人来安装 其实安装系统这个过程并不算太难 我会慢慢向大家介绍安装系统的各种方法 首先要说的第一种自然是安装原版系
  • 超好用的pdf编辑+pdf转word工具 – Adobe Acrobat Pro DC下载

    Adobe Acrobat DC 是一款 PDF 的处理工具 下面我来给大家说一说这款软件相关内容 Adobe Acrobat Pro DC 是一款由 Adobe 官方推出的 PDF 编辑和阅读软件 是目前互联网上最专业最优秀的桌面 pdf
  • JavaScript中为什么0.1+0.2 不等于 0.3?

    1 问题现状 0 1 0 2 0 3 这个等式的成立看起来是理所当然的 然而事实并非如此 这个属于JS运算中精度的缺失问题 所以0 1 0 2 0 3 2 问题原因 因为计算机硬件存储数据时 是以二进制 10101010 形式进行存储的 所
  • oceanbase的数据视图

    文章目录 一 OceanBas 系统视图 1 1 字典视图 1 1 1 Help 命令 1 1 2 SPM 相关 1 1 3 权限相关 1 1 4 调度程序 1 1 5 存储相关 1 1 6 时区相关 1 1 7 字符集 1 1 8 表和列
  • Spring Boot日志详解

    目录 1 日志的抽象与实现 2 配置文件 2 1 application properties 2 2 application properties与logback spring xml的优先级 3 logback spring xml标签
  • golang的xml解析

  • 第五章 变形

    文章目录 一 长宽表的变形 1 pivot 2 pivot table 练一练 END 3 melt 4 wide to long 二 索引的变形 1 stack与unstack 2 聚合与变形的关系 三 其他变形函数 1 crosstab
  • Vue.js的组件(一)全局组件和局部组件

    刚开始学习Vue js 记录下心得 所谓组件 在我看来 就相当于新建一个属于自己的标签 但是这个标签的功能很强大 可以有很多特殊的功能 组件可以全局声明 js Vue component my component button1 templ
  • 环县计算机培训班,庆阳中职学校排名前十

    甘肃省庆阳市西峰区陇东职业中等专业学校建于1988年 是一所国家级重点职业学校 中德合作项目学校 学校位于庆阳市西峰区董志镇南街 毗邻庆阳市南区开发区 市内1路公交车南终点站 交通便利 环境优美 学校占地面积152亩 校舍建筑面积3 62万
  • 教你如何实现带复选框的ComboBox(自定义QComboBox)

    Qt提供的QComboBox只能选择其中一个选项 无法实现同时选中多个 而实际工程项目中 下拉框中带复选框的需求比比皆是 阅读了网上大量的博客 但是没有发现一个能完美的实现该功能的ComboBox 都存在各种未解决的bug缺陷 样子是那么回
  • 央企数字化转型实践思考

    01 数字化转型的内涵与价值效益 数字化转型是顺应新一轮科技革命和产业变革趋势 不断深化应用云计算 大数据 物联网 人工智能 区块链等新一代信息技术 激发数据要素创新驱动潜能 打造和提升信息时代的生存与发展能力 加速业务优化升级和创新转型
  • Python爬虫:如何下载汽车之家的数据(完整代码)

    欢迎来到我的博客 作者 秋无之地 简介 CSDN爬虫 后端 大数据领域创作者 目前从事python爬虫 后端和大数据等相关工作 主要擅长领域有 爬虫 后端 大数据开发 数据分析等 欢迎小伙伴们点赞 收藏 留言 关注 关注必回关 一 确定目标
  • C语言 项目 CRM系统(客户信息管理系统)

    项目目标 项目需求说明 系统界面 1 添加客户界面 通过编号来区分客户 2 删除客户界面 对用户输入的编号进行核查 存在与否 合法与否 3 显示客户列表界面 4 修改客户信息的界面 项目设计 Customer结构体的设计 CRM系统结构框架
  • 基于机器学习方法对销售预测的研究

    很高兴 InfoQ 团队和 百分点大数据学院 牵头举办此次活动 百分点大数据学院 是由百分点发起的大数据领域专业 开放的分享交流平台 通过定期举办线上线下活动 邀请大数据领域学术专家 技术领袖 企业高层 分享行业 技术 应用等方面最前沿的经
  • PowerMock(一):PowerMock的基本使用

    文章目录 为啥要使用PowerMock PowerMock的使用 环境 引入依赖 注解说明 mock普通方法 mock抛出异常 mock新建对象 mock无返回值的方法 mock被final修饰的方法 参数模糊匹配 mock静态方法 moc