Mockito
1.简介
Mockito 是一种 Java Mock 框架,主要是用来做 Mock 测试,
它可以模拟任何 Spring 管理的 Bean、模拟方法的返回值、模拟抛出异常等等
用于快速创建和配置mock对象。通过创建外部依赖的 Mock 对象, 然后将此 Mock 对象注入到测试类中,简化有外部依赖的类的测试。
我们注重于方法内的逻辑测试即可
2.概念介绍
常用注解
Mockito框架中包含了一些常用的注解,下面是对这些注解的详细解释:
-
@Mock:用于创建一个Mock对象。这个注解创建的Mock对象不会自动注入到Spring容器中。
-
@MockBean:用于创建一个Mock对象,并将其添加到Spring容器中。这个注解通常用于Spring Boot的集成测试中。
-
@InjectMocks:用于创建一个实例,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中。
-
. @Spy:用于创建一个Spy对象。Spy对象是一种特殊的Mock对象,它默认会调用真实的方法。
-
@Captor:用于创建一个参数捕获器。参数捕获器可以用来捕获方法调用的参数值。
-
@BeforeEach:标记在方法上,表示该方法应该在每个测试方法之前执行。
-
@AfterEach:标记在方法上,表示该方法应该在每个测试方法之后执行。
-
@BeforeAll:标记在方法上,表示该方法应该在所有测试方法之前执行一次。
-
@AfterAll:标记在方法上,表示该方法应该在所有测试方法之后执行一次。
3.mockito使用
注意事项
需要结合Junit使用(普通的Spring项目)
springboot项目的话,boot-test包默认已经引入mockito相关
前期准备
普通的spring项目,倒入相关jar包,
需要结合junit使用
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<!--下面几个非强制。根据实际情况决定是否添加-->
<!--mockito模拟static方法需要引⼊-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<!--mockito断言匹配器-->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<scope>test</scope>
</dependency>
<!--mockito流式断言,比junit自带的assert更强⼤,更不容易出错-->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
springBoot项目的话就无需这些,starter-test包里自带
结合Spring项目使用
基本使用
/**
* @author xwp
* @date 2023/12/5 14:25
*/
@RunWith(MockitoJUnitRunner.class)
public class DeviceFacadeImplTest {
private Logger logger = LoggerFactory.getLogger(getClass());
@InjectMocks
private DeviceFacadeImpl deviceFacade;
@Mock
private IEmMemberDeviceService emMemberDeviceService;
@Before
public void setUp() throws Exception {
}
/**
* 测试--正常流程
*/
@Test
public void testOpenAutoStreaming() {
//构建目标方法的请求参数--com.fzs.server.service.facade.DeviceFacade.openAutoStreaming
OpenStreamingParam openStreamingParam = new OpenStreamingParam();
openStreamingParam.setUserId("1");
openStreamingParam.setStreamType(1);
openStreamingParam.setInstanceId("1");
String memberId = "1";
//制造条件 mock其他服务返回数据
EmMemberDevice emMemberDevice = new EmMemberDevice();
emMemberDevice.setDeviceRunningStatus(1);
emMemberDevice.setStatus(50);
emMemberDevice.setFrozenStatus(0);
emMemberDevice.setDeviceId("1");
emMemberDevice.setPhoneId("1");
when(emMemberDeviceService.getOne(any())).thenReturn(emMemberDevice);
//测试调用目标方法
OpenAutoStreamResult openAutoStreamResult = deviceFacade.openAutoStreaming(memberId, openStreamingParam);
logger.info("返回结果,{}", openAutoStreamResult);
}
}
4.常见场景
1.如何mock@Value引入的属性
可以用反射+@Before
@Before:在目标方法执行前会调用(在junit 5.x中,@Before主键被@BeforeEach所替代。)
@Before
public void setUp() throws Exception {
//mock设置@Value的值 (反射)
Field field = DeviceFacadeImpl.class.getDeclaredField("enableADN");
field.setAccessible(true);
field.set(deviceFacade, false);
}
2.返回void的方法mock?
doNothing
doNothing().when(stringValueOperations).set(any(String.class), any(String.class));
3.如何mock redisTemplate的set/get方法
在@Before里面mock valueOperations对象,然后在@Test方法mock调用其set/get
@Mock
RedisTemplate<String, Object> redisTemplate;
@Mock
private ValueOperations<String, Object> valueOperations;
@Before
public void setUp() throws Exception {
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
}
@test1
public void test1() throws Exception {
when(valueOperations.get(any())).thenReturn(1);
doNothing().when(valueOperations).set(any(String.class), any(Object.class), any(long.class), any(TimeUnit.class));
}
4.mybatisPlus在使用Lambda表达式处理查询问题?
如果在mybatisPlus使用了lambda表达式的查询的话,调用mock对象emDevicesStreamsService的getOne方法,例如:
EmDevicesStreams ds = emDevicesStreamsService.getOne(new QueryWrapper<EmDevicesStreams>().lambda().eq(EmDevicesStreams::getDeviceId, deviceId).orderByDesc(EmDevicesStreams::getId).last(" LIMIT 1 "));
会报错:
can not find lambda cache for this entity [com.fzs.server.service.entity.EmDevicesStreams
这个问题是由于MyBatis Plus在处理Lambda表达式时,需要获取实体类的元数据,但在Mock环境中,由于类加载器的问题,可能无法正确获取这些元数据,从而导致这个错误。
解决:
在@Before里面添加:
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), EmDevicesStreams.class);
具体原因分析参考:
https://blog.csdn.net/qq_36491545/article/details/109091325
标签:Mockito,class,Mock,方法,any,mock,Before From: https://www.cnblogs.com/cutesheep/p/17879508.html