Skip to content

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 的核心就三件事:

  1. 设置假行为when(mock.method()).thenReturn(...)
  2. 执行被测方法
  3. 验证:验证返回结果 + 验证方法被调用

Mock 不是欺骗,是让测试只关注被测类本身,不被外部依赖干扰。

基于 VitePress 构建