Junit4下Mockito包的使用

Spring环境下的单元测试--Junit4下Mockito包的使用

1.Mockito包是做什么的?

Mockito 是一个强大的 Java 单元测试框架,用于创建和管理 Mock 对象,帮助开发者在测试中模拟复杂的依赖关系。它通过简洁的 API 和强大的功能,使单元测试更加高效和易于维护。

​ 其实也就是帮助我创建一些对象,并且赋值上默认值,当然,这是针对方法也可以直接返回一个特定的想要的值,让我们除去复杂的数据而直接检验方法的逻辑。

2.怎么用?

<1>.注解使用

​ 先看Mokcito中的一些注解(以Junit4举例)

注解 作用 注意事项
@RunWith(SpringRunner.class) Spring进入测试生命周期的标识
@Mock 模拟一个对象,全部属性赋上默认值,里边的值都是虚拟的 mock的对象不可以再手动set其对应的属性,不会生效
@Spy 模拟一个真实对象,修改特定方法或属性,未修改的保留原有真实对象
@InjectMocks 将Mock的对象注入使用注解的对象中 一般来说你测试哪个类,就用在哪个类上

​ 这几个注解已经足够满足大部分的单元测试,当然还有一个静态方法的模拟。

​ 由于静态方法是类,并不为对象,对此@Mock和@Spy注解无能为力,那那么就该另一个注解登场,或者是不使用注解。

​ 先看注解:@MockStatic,之后还需要写一个MockStatic<你的对象>

java 复制代码
@MockStatic(你的对象.class)
private MockStatic<你的对象> 别名;

​ 不过建议放在ry-with-resources中,可以在使用完静态方法后自动关闭,防止脏数据影响到其他测试。

java 复制代码
 try (MockedStatic<你的对象> mocked = mockStatic(你的对象.class)) {
     //写具体的调用
 }

​ 讲完注解的,说说不用注解的

java 复制代码
//先创建对象
private MockedStatic<你的对象> 别名;
//在测试中的加上@before注解的方法中首先进行加载
别名 = Mockito.mockStatic(你的对象.class);
别名.when( () -> 你的对象.静态方法(参数)).thenReturn(具体值);
//这个时候还需要进行关闭,防止数据污染,在@after注解使用的方法中关闭
this.别名.close();
<2>.方法的调用

​ 一般来说都是用when进行包裹,这是Mockito中的一个静态方法

复制代码
框架大概为:
when(别名.方法(可填各种参数匹配的规则类型)).返回一个特定类型
1>. 返回特定值
java 复制代码
//下边解释为:当调用metaModelDao.findBySelectedIds()这个方法的时候,匹配的参数如果为任意的一个Sting数组的类,即返回一个自定义的result对象
when(metaModelDao.findBySelectedIds(any((String[].class)))).thenReturn(result);

//参数匹配还有哪些
when(metaModelDao.findBySelectedIds(eq("一个值或者是想要的对象等,一般用来比对值")))
    .thenReturn(result);

​ 参数匹配器大家可自行查阅,这里不做赘述,有了框架根据需求套就可以。

2>.动态返回值

​ 被测试的方法中对象不可能总是去手动打桩或者去mock,有的对象是会在方法中动态更新的。

​ 举一个例子来说:

​ 我现在需要修改一条数据,等到修改完毕之后 ,我需要从数据库中检查一下我的数据是否更新,那么此时我就需要再次调用一个dao层中的方法来获取,但在测试的时候完全没有必要这样,因为我们做单元测试一般来说会去做service层的测试,dao对象很明显就是mock出来的,那么它的方法也基本都是用when()来mock出来的,所以当其再查询一次的话,我就可以直接给他返回一个被测试方法中的对象,代码如下:

​ 原方法如下

java 复制代码
public void updateUser(User user,PromptMessage promptmessage){
    //检查判空等操作先不管
    User user = userDao.findOne(user);
    user.setAge(18);
    //类似于这种,具体逻辑先不管,此时的这个方法就没有必要再去mock了,直接把这个user返回就行了
    User user = userDao.update(user);
    ......
}

//测试方法
//解释:返回传入方法的第一个参数,第二个可以改变下标
when(userDao.update(any(User.class))).thenAnswer(ino -> ino.getArgument(0));
3>. 检验

​ 这是测试的关键一步,决定是否测试通过的一步。

​ Assert断言是经常被用到的。

java 复制代码
assertEquals(预期值,实际值);
//测试某个方法被调用了多少次,Times(1)可以省略,省略即默认为测试调用1次
verify(mock的类,Times(1)).方法(参数);

掌握这些基本可以解决90%的问题,剩下的问题就是不停的mock,mock,mock,打桩

相关推荐
好好沉淀1 小时前
Java 开发环境概念速查笔记(JDK / SDK / Maven)
java·笔记·maven
凹凸曼coding1 小时前
Java业务层单元测试通用编写流程(Junit4+Mockito实战)
java·单元测试·log4j
C雨后彩虹1 小时前
Java 并发程序性能优化:思路、方法与实践
java·线程·多线程·并发
!停1 小时前
数据结构空间复杂度
java·c语言·算法
她说..2 小时前
验签实现方案整理(签名验证+防篡改+防重放)
java·经验分享·spring boot·java-ee·bladex
爱吃山竹的大肚肚2 小时前
异步导出方案
java·spring boot·后端·spring·中间件
没有bug.的程序员2 小时前
Spring Boot 与 Redis:缓存穿透/击穿/雪崩的终极攻防实战指南
java·spring boot·redis·缓存·缓存穿透·缓存击穿·缓存雪崩
草履虫建模2 小时前
Java 基础到进阶|专栏导航:路线图 + 目录(持续更新)
java·开发语言·spring boot·spring cloud·maven·基础·进阶
Zhu_S W2 小时前
Java多进程监控器技术实现详解
java·开发语言