当前位置:网站首页>Mockito基本使用指南
Mockito基本使用指南
2022-08-10 05:30:00 【m0_67403073】
What’s Mockito
Mockito是Java单元测试开发框架。在写测试单元时它可以Mock(模拟)开发中一些未完成的接口或者网络断开、数据库连接错误等方法调用。Mockito很强大文中有限还有很多使用方式未提及,请参考官方文档。官方文档链接在文章尾部给出。
eq:when() 多个参数或者搭配List根据不同index设置返回结果。
QuickStart
为了更好的表达使用一个Mock DAO层的场景,数据库还没能正常使用时但是又急需测试功能逻辑是否正确。
mapper---|
UserMapper.java
mapperImpl---|
UserMapperImpl.java
service---|
UserService.java
//UserMapper.java
public interface UserMapper
{
User selectOne(Integer id);
void print();
}
public class UserMapperImpl implements UserMapper{
@Override
public User selectOne(Integer id) {
return null;
}
@Override
public void print() {
System.out.println("test");
}
}
//UserService.java UserService通过@Configuration配置由Spirng IOC管理
public class UserService
{
@Autowired
UserMapper userMapper;
public User getOne(Integer id)
{
return userMapper.selectOne(id);
}
}
第一步 添加依赖
Java 环境依赖
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.4.0</version>
</dependency>
SpringBoot 环境依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
第二步 mock对象与Stubbing
因为数据库无法正常使用的原因,但是service由依赖userMapper的selectOne方法,只能去mock一个假的userMapper。mock一个假的userMapper只需要使用注解@MockBean
SpringBoot会自动代替注入一个假的userMapper给service。具体原理是userMapper生成一个代理对象。
when()
静态方法用于Stubbing(方法打桩),参数为非private 、final的方法调用。thenReturn
设置被Stubbing的方法返回值。
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.mockito.Mockito.when;
@SpringBootTest
class MockitoDemoTests {
@MockBean
UserMapper userMapper;
@Autowired
UserService userService;
@Test
void mockUserMapper() {
when(userMapper.selectOne(0)).thenReturn(new User()); //这里mock的是userMapper的方法,service间接调用。
User user = userService.getOne(0);
assertThat(user,notNullValue()); //断言不为空
}
}
//Tests passed:1
More
built-in runner
使用Mockito的注解需要在JUnit5构建mock环境
加上类注解@ExtendWith(MockitoExtension.class)
Mock
使用mock创建一个代理对象。代理对象的方法调用返回都是java基本类型默认返回值。
1、使用mock方法
UserMapper userMapper= Mockito.mock(UserMapper.class); //不由Spring管理
2、使用@Mock注解 ,需要基于JUnit5环境。
@Mock
UserMapper userMapper; //不由Spring管理
配合@InjectMocks
注解可以注入到userService。
@Mock
UserMapper userMapper;
@InjectMocks
UserService userService;
3、使用Springboot的@MockBean注解,Spring会自动注入到测试环境里所需要依赖的对象。
@MockBean
UserMapper userMapper;
Spy
有时候需要在真实对象上mock方法,使用spy可以创建或者放入一个真实对象进行Stubbing,用spy创建的对象都是真实对象。
1、使用spy方法
UserMapper userMapper= Mockito.Spy(Object);
2、使用@spy注解,需要基于JUnit5环境。
@Spy
UserMapper userMapper=new UserMapperImpl();
配合@InjectMocks
注解可以注入到userService。
@Spy
UserMapper userMapper;
@InjectMocks
UserService userService;
3、使用Springboot的@SpyBean注解
@SpyBean
UserMapper userMapper;
When
when可以对调用方法进行代理Stubbing方法返回值、方法异常
mock selectOne(0) 方法返回值,thenReturn参数为调用方法期望返回值。
when(userMapper.selectOne(0)).thenReturn(new User());
mock selectOne(0) 方法异常,当调用selectOne(0) 时会抛出异常。
when(userMapper.selectOne(0)).thenThrow(new TimeoutException());
当一个void方法不需要执行时可以使用 doNothing().when()
import org.mockito.*;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class MockitoDemoTests {
@Spy
UserMapper userMapper=new UserMapperImpl();
@Test
void mockUserMapper() {
doNothing().when(userMapper).print();
userMapper.print();
}
}
//没有任何输出
Argument matchers
当使用when去Stubbing方法时可以根据被调用方法传参做不同的返回值或异常。
when(userMapper.selectOne(0)).thenReturn(new User());
when(userMapper.selectOne(1)).thenReturn(new User());
User userId0 = userService.getOne(0);
User userId1 = userService.getOne(1);
assertThat(userId0,not(equalTo(userId1))); //断言是否是一个对象
//passed:1
//可以看到getOne(0)和getOne(1)不一致。
官方内置了很多类型的静态方法包含了很多场景。比如anyInt()
表示传参任何int类型数字都可以。
any() //任何对象
any{基本类型}()
@Test
void mockUserMapper() {
User user=new User();
when(userMapper.selectOne(anyInt())).thenReturn(user);
User userId0 = userService.getOne(0);
assertThat(userId0,equalTo(user));//断言是否是一个对象
}
//passed:1
//可以看到user和userId0是一致。
需要注意的是 when(userMapper.selectOne(anyInt()))
会被when(userMapper.selectOne(0))
条件覆盖。
如果when里使用了官方内置类型any()
方法其参数也应该使用。如果有指定参数可以使用eq()
when(xxx.xxx(any(),"text"))
when(xxx.xxx(any(),eq("text"))
Verification
验证被mock方法的动作
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.*;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class MockitoDemoTests {
@Spy
UserMapper userMapper=new UserMapperImpl();
@Test
void mockUserMapper() {
doNothing().when(userMapper).print();
userMapper.print();
verify(userMapper,times(1)).print(); //验证print()至少调用一次。
}
}
//passed:1
参考文档:
https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.mocking-beans
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦
边栏推荐
猜你喜欢
PyTorch 入门之旅
[Thesis Notes] Prototypical Contrast Adaptation for Domain Adaptive Semantic Segmentation
Pony语言学习(一):环境配置(续)
基于Qiskit——《量子计算编程实战》读书笔记(二)
R语言:修改chart.Correlation()函数绘制相关性图——完美出图
Qiskit官方文档选译之量子傅里叶变换(Quantum Fourier Transform, QFT)
一篇文章带你搞懂什么是幂等性问题?如何解决幂等性问题?
基于Qiskit——《量子计算编程实战》读书笔记(四)
Buu Web
深度学习中数据到底要不要归一化?实测数据来说明!
随机推荐
实战小技巧19:List转Map List的几种姿势
深度学习中的学习率调整策略(1)
论文精读 —— 2021 CVPR《Progressive Temporal Feature Alignment Network for Video Inpainting》
大咖说·对话生态|当Confluent遇见云:实时流动的数据更有价值
Pony语言学习(六):Struct, Type Alias, Type Expressions
GtkD开发之路
Stacks and Queues | Valid parentheses, delete all adjacent elements in a string, reverse Polish expression evaluation, maximum sliding window, top K high frequency elements | leecode brush questions
基于Qiskit——《量子计算编程实战》读书笔记(五)
oracle rac 11g安装执行root.sh时报错
网安超基础一周目
从GET切换为POST提交数据的方法
一篇文章带你搞懂什么是幂等性问题?如何解决幂等性问题?
FPGA工程师面试试题集锦31~40
来亲自手搭一个ResNet18网络
How does Jenkins play with interface automation testing?
每周推荐短视频:探索AI的应用边界
pytorch框架学习(2)使用GPU训练
看了几十篇轻量化目标检测论文扫盲做的摘抄笔记
基于Qiskit——《量子计算编程实战》读书笔记(六)
Pony语言学习(八):引用能力(Reference Capabilities)