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,打桩

相关推荐
金銀銅鐵14 小时前
浅解 JUnit 4 第十篇:方法上的 @Ignore 注解
junit·单元测试
华仔啊15 小时前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing15 小时前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠1 天前
各版本JDK对比:JDK 25 特性详解
java
用户8307196840821 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide1 天前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家1 天前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java
花花无缺1 天前
搞懂new 关键字(构造函数)和 .builder() 模式(建造者模式)创建对象
java
用户908324602731 天前
Spring Boot + MyBatis-Plus 多租户实战:从数据隔离到权限控制的完整方案
java·后端
桦说编程1 天前
实战分析 ConcurrentHashMap.computeIfAbsent 的锁冲突问题
java·后端·性能优化