Mockito 入门:Mock 对象的心法
写单元测试时,被测的类往往依赖其他类——数据库、HTTP 客户端、外部服务。这些依赖不应该出现在单元测试里。
于是有了 Mock:用假的对象替代真实的依赖。
Mock vs Spy
| 类型 | 含义 | 适用场景 |
|---|---|---|
| Mock | 完全假的对象,方法调用按预设返回 | 大部分情况 |
| Spy | 部分真的对象,默认调用真实方法,可选择性 Mock | 只想 Mock 一部分 |
java
// Mock:全是假货
List<String> mockList = mock(List.class);
mockList.add("hello"); // 不执行任何操作
mockList.get(0); // 返回 null
when(mockList.size()).thenReturn(10); // 预设行为
// Spy:部分真货
List<String> spyList = spy(new ArrayList<>());
spyList.add("hello"); // 执行真实的 add
when(spyList.size()).thenReturn(10); // 但 size() 返回 10基础使用
java
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void testGetUser() {
// 设置 mock 行为
when(userRepository.findById(1L))
.thenReturn(new User("张三"));
// 执行
User user = userService.getUser(1L);
// 验证
assertEquals("张三", user.getName());
verify(userRepository).findById(1L); // 验证方法被调用
}
}Mock 行为设置
java
@Test
void testMockBehaviors() {
// 返回值
when(mock.method()).thenReturn("value");
// 抛异常
when(mock.method()).thenThrow(new RuntimeException("error"));
// 连续调用返回不同值
when(mock.method())
.thenReturn("first")
.thenReturn("second")
.thenThrow(new RuntimeException());
// 参数匹配
when(mock.method(anyString())).thenReturn("matched");
when(mock.method(eq("hello"))).thenReturn("exact match");
}验证调用
java
@Test
void testVerification() {
// 验证调用次数
verify(mock, times(2)).method();
// 验证至少一次
verify(mock, atLeastOnce()).method();
// 验证从未调用
verify(mock, never()).otherMethod();
// 验证调用顺序
InOrder inOrder = inOrder(mock);
inOrder.verify(mock).method1();
inOrder.verify(mock).method2();
}常用匹配器
| 匹配器 | 含义 |
|---|---|
anyString() | 任意字符串 |
anyInt() / anyLong() 等 | 任意数字 |
any() | 任意对象(包括 null) |
isNull() | null |
eq(value) | 精确匹配 |
contains(substring) | 包含子串 |
argThat(predicate) | 自定义匹配逻辑 |
java
when(mock.method(argThat(s -> s.length() > 3))).thenReturn("matched");总结
Mock 的核心就三件事:
- 设置假行为:
when(mock.method()).thenReturn(...) - 执行被测方法
- 验证:验证返回结果 + 验证方法被调用
Mock 不是欺骗,是让测试只关注被测类本身,不被外部依赖干扰。
