Mockito 5.x使用
·
1、添加依赖
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.20.0</version>
<scope>test</scope>
</dependency>
<!-- 如果使用 JUnit 5 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.20.0</version>
<scope>test</scope>
</dependency>
2、测试类写法(标准模板)
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
// 开启 Mockito
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
// 模拟依赖(假对象)
@Mock
private UserDao userDao;
// 要测试的类,自动注入 mock
@InjectMocks
private UserService userService;
@Test
void testGetUser() {
// 1. 模拟返回值
User mockUser = new User(1L, "mock-name");
when(userDao.getById(1L)).thenReturn(mockUser);
// 2. 调用业务方法
User result = userService.getById(1L);
// 3. 断言
assertEquals("mock-name", result.getName());
// 4. 验证方法调用
verify(userDao).getById(1L);
}
}
3、Mockito 5.20.0 核心功能
模拟返回任意值
// 固定值
when(userDao.getById(1L)).thenReturn(new User(1L, "张三"));
// 多个返回(依次返回)
when(userDao.getById(1L)).thenReturn(u1, u2, u3);
thenAnswer
动态回调应答,可根据实际入参动态计算返回值、自定义逻辑,比固定thenReturn灵活。
@Test
void testThenAnswerParam() {
when(userDao.getById(anyLong())).thenAnswer(invocation -> {
// 获取实际传入的参数
Long id = invocation.getArgument(0);
// 根据参数动态返回
return new User(id, "动态用户"+id);
});
User u1 = userService.getById(1L);
User u2 = userService.getById(2L);
assertEquals("动态用户1", u1.getName());
assertEquals("动态用户2", u2.getName());
}
模拟抛出异常
// 有返回值方法
when(userDao.getById(null)).thenThrow(IllegalArgumentException.class);
// void 方法(5.x 推荐写法)
doThrow(RuntimeException.class).when(userDao).delete(anyLong());
参数匹配器(万能写法)
// 任意 Long
when(userDao.getById(anyLong())).thenReturn(user);
// 任意对象
when(userDao.save(any(User.class))).thenReturn(true);
// 不为 null
when(userDao.getById(notNull())).thenReturn(user);
验证调用次数(非常常用)
// 调用 1 次
verify(userDao).getById(1L);
// 调用 2 次
verify(userDao, times(2)).getById(1L);
// 从未调用
verify(userDao, never()).delete(any());
捕获参数(拿到传入的对象)
import org.mockito.ArgumentCaptor;
@Test
void testCapture() {
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
userService.save(new User(1L, "test"));
verify(userDao).save(captor.capture());
User saved = captor.getValue();
assertEquals(1L, saved.getId());
}
4、Mockito 5 最强特性:原生支持 静态方法 / 构造方法 /final 类
模拟静态方法(如 UUID、LocalDateTime)
@Test
void testStatic() {
try (var mocked = mockStatic(UUID.class)) {
mocked.when(UUID::randomUUID)
.thenReturn(UUID.fromString("1-1-1-1-1"));
assertEquals("1-1-1-1-1", UUID.randomUUID().toString());
}
}
模拟构造方法(new 对象时返回 mock)
@Test
void testConstructor() {
try (var mocked = mockConstruction(ArrayList.class)) {
List<String> list = new ArrayList<>(); // 自动变成 mock
when(list.size()).thenReturn(100);
assertEquals(100, list.size());
}
}
模拟 final 类 /final 方法(5.x 原生支持)
@Mock
private FinalUserDao finalUserDao; // final 类也能 mock
@Test
void testFinal() {
when(finalUserDao.get(anyLong())).thenReturn(new User());
}
5、Spy:部分真实、部分模拟
@Spy
private UserDao userDao; // 真实对象
@Test
void testSpy() {
// 只模拟这一个方法
when(userDao.getById(1L)).thenReturn(new User(1L, "spy"));
// 模拟结果
User u1 = userDao.getById(1L);
// 真实方法
User u2 = userDao.getById(2L);
}
6、5.20.0 严格模式(默认更严格,避免烂测试)
// 宽松模式:允许没用到的 stub(不报错)
@Mock(strictness = Strictness.LENIENT)
private UserDao userDao;
7、最容易踩的坑
- 不要再用 PowerMock → Mockito 5 已原生支持静态、构造、final
- 不要引入 mockito-inline → 5.x 已内置,加了会冲突
- 必须 Java 11+
- 静态 / 构造模拟必须用 try-with-resources 自动关闭
- void 方法必须用 doThrow() / doNothing()
8、一句话总结
- @Mock:创建假对象
- @InjectMocks:把假对象注入测试类
- when(…).thenReturn(…):模拟返回
- verify(…):验证调用
- mockStatic / mockConstruction:模拟静态 / 构造(5.x 最强功能)
更多推荐




所有评论(0)