TEST 九月 14, 2025

【转】Mockito Core 与 Mockito Inline 的区别

文章字数 5.6k 阅读约需 5 mins. 阅读次数

1. 概述

Mockito 是 Java 中最流行的模拟对象框架之一,它提供了 Mockito Core 和 Mockito Inline 两个核心库,用于满足单元测试中不同场景的需求。

✅ 想深入学习 Mockito 测试技巧?可以参考我们的 Mockito 系列教程

2. Mockito Core

Mockito Core 是 Mockito 的基础库,提供创建模拟对象(Mock)、桩对象(Stub)和间谍对象(Spy)的核心功能。对于大多数常见场景,这个库已经足够,但存在明显限制:

无法模拟 final 类和静态方法

无法修改 final 字段

无法拦截构造函数

⚠️ 基础用法示例可参考这里

3. Mockito Inline

Mockito Inline 是 Mockito Core 的扩展版本,专门解决 Core 版本的限制。从 Mockito Core 5.0.0 开始,它已成为默认的模拟生成器。

3.1 模拟 final 类

首先创建一个 final 类:

public final class FinalClass {
    public String greet() {
        return "Hello, World!";
    }
}

测试代码示例:

@Test
void testFinalClassMock() {
    FinalClass finalClass = mock(FinalClass.class);
    when(finalClass.greet()).thenReturn("Mocked Greeting");

    assertEquals("Mocked Greeting", finalClass.greet());
}

核心逻辑: 我们将 greet() 方法原本返回的 “Hello, World!” 替换为 “Mocked Greeting”,这是传统 Core 版本无法实现的。

3.2 模拟 final 字段

创建包含 final 字段的类:

public class ClassWithFinalField {
    public final String finalField = "Original Value";

    public String getFinalField() {
        return finalField;
    }
}

测试代码:

@Test
void testFinalFieldMock() {
    ClassWithFinalField instance = mock(ClassWithFinalField.class);
    when(instance.getFinalField()).thenReturn("Mocked Value");

    assertEquals("Mocked Value", instance.getFinalField());
}

踩坑指南: 这里通过模拟 getFinalField() 方法绕过了 final 字段的不可变性,直接返回预设值 “Mocked Value”。

3.3 模拟静态方法

创建含静态方法的类:

public class ClassWithStaticMethod {
    public static String staticMethod() {
        return "Original Static Value";
    }
}

测试实现:

@Test
void testStaticMethodMock() {
    try (MockedStatic<ClassWithStaticMethod> mocked = mockStatic(ClassWithStaticMethod.class)) {
        mocked.when(ClassWithStaticMethod::staticMethod).thenReturn("Mocked Static Value");

        assertEquals("Mocked Static Value", ClassWithStaticMethod.staticMethod());
    }
}

关键点: 使用 mockStatic() 创建静态方法模拟上下文,在 try-with-resources 块内替换方法行为。

3.4 模拟构造函数

创建含构造函数的类:

public class ClassWithConstructor {
    private String name;

    public ClassWithConstructor(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
}

测试代码:

@Test
void testConstructorMock() {
    try (MockedConstruction<ClassWithConstructor> mocked = mockConstruction(ClassWithConstructor.class,
            (mock, context) -> when(mock.getName()).thenReturn("Mocked Name"))) {

        ClassWithConstructor myClass = new ClassWithConstructor("test");
        assertEquals("Mocked Name", myClass.getName());
    }
}

简单粗暴: 通过 mockConstruction() 拦截所有新实例创建,强制 getName() 返回 “Mocked Name” 而非构造参数 “test”。

4. 功能对比总结

模拟目标 Mockito Core Mockito Inline
Final 类 ❌ 不支持 ✅ 支持
Final 字段 ❌ 不支持 ✅ 支持
静态方法 ❌ 不支持 ✅ 支持
构造函数 ❌ 不支持 ✅ 支持

5. 结论

Mockito Core 和 Inline 的核心区别非常明确:

  • Mockito Core:适用于基础模拟场景,但遇到 final 类/方法、静态成员或构造函数时会束手无策。
  • Mockito Inline:完美解决 Core 的所有限制,支持模拟 final 类、final 字段、静态方法和构造函数,是复杂测试场景的终极解决方案。

💡 实际开发建议:直接使用 Mockito Core 5.0.0+(默认集成 Inline),避免因版本差异踩坑。

0%