当前位置 : 主页 > 网络编程 > 其它编程 >

Mockito基本使用指南

来源:互联网 收集:自由互联 发布时间:2023-07-02
What’sMockito?Mockito是Java单元测试开发框架。在写测试单元时它可以Mock(模拟)开发中一些未完成的接口或者网络断开、数据库连接错误等方法调用。Mockit What’s Mockito ? Mockito是Java单元测
What’sMockito?Mockito是Java单元测试开发框架。在写测试单元时它可以Mock(模拟)开发中一些未完成的接口或者网络断开、数据库连接错误等方法调用。Mockit What’s Mockito ?

Mockito是Java单元测试开发框架。在写测试单元时它可以Mock(模拟)开发中一些未完成的接口或者网络断开、数据库连接错误等方法调用。Mockito很强大文中有限还有很多使用方式未提及,请参考官方文档。官方文档链接在文章尾部给出。 eq:when() 多个参数或者搭配List根据不同index设置返回结果。

QuickStart

为了更好的表达使用一个Mock DAO层的场景,数据库还没能正常使用时但是又急需测试功能逻辑是否正确。

mapper---| UserMapper.javamapperImpl---| UserMapperImpl.javaservice---| UserService.java

//UserMapper.javapublic 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 环境依赖

org.mockito mockito-core 4.4.0

SpringBoot 环境依赖

org.springframework.boot spring-boot-starter-test

第二步 mock对象与Stubbing

因为数据库无法正常使用的原因,但是service由依赖userMapper的selectOne方法,只能去mock一个假的userMapper。mock一个假的userMapper只需要使用注解@MockBeanSpringBoot会自动代替注入一个假的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;@SpringBootTestclass 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:1More

built-in runner

加上类注解@ExtendWith(MockitoExtension.class)

Mock

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

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

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(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{基本类型}()

@Testvoid 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

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

网友评论