Skip to content

解决 Mockito 警告:未来 JDK 版本中禁用动态加载代理

问题描述

在使用 Spring Boot 运行测试时(特别是 JDK 21+ 环境),会出现以下警告信息:

text
Mockito is currently self-attaching to enable the inline-mock-maker. 
This will no longer work in future releases of the JDK. 
Please add Mockito as an agent to your build...

WARNING: A Java agent has been loaded dynamically...
WARNING: Dynamic loading of agents will be disallowed by default in a future release
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes...

核心问题:Mockito 尝试动态加载 Java 代理(inline-mock-maker),但未来 JDK 版本将默认禁用这种动态加载行为。这会影响使用 Mockito 进行测试代码的功能,特别是涉及静态方法或 final 类/方法的 Mock 操作。

技术背景

  • JDK 21+ 开始限制动态加载 Java 代理
  • Mockito 5.x+ 默认依赖 mockito-inline 增强功能
  • 问题在 Spring Boot 3.x + JDK 17+ 环境尤为常见

解决方案汇总

通过配置构建工具将 Mockito 作为 Java Agent 启动,同时禁用类共享(class data sharing)。

Maven 配置方案(推荐)

pom.xml 中配置 maven-surefire-plugin

xml
<properties>
    <mockito.version>5.17.0</mockito.version> <!-- 与项目实际版本一致 -->
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.5.2</version> <!-- 推荐使用3.0.0+ -->
            <configuration>
                <argLine>
                    -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
                    -Xshare:off
                </argLine>
            </configuration>
        </plugin>
    </plugins>
</build>

注意

  1. 不需要额外配置 maven-dependency-plugin
  2. -Xshare:off 解决类共享相关警告
  3. 确认 mockito.version 与实际依赖版本一致

Gradle 配置方案(Groovy DSL)

groovy
// 定义专用配置
configurations {
    mockitoAgent {
        transitive = false
    }
}

dependencies {
    // 其他依赖...
    testImplementation 'org.mockito:mockito-core' // 确保已存在
    mockitoAgent 'org.mockito:mockito-core'       // 添加到Agent配置
}

test {
    jvmArgs = [
        // 解决Mockito警告
        "-javaagent:${configurations.mockitoAgent.asPath}",
        // 解决类共享警告
        "-Xshare:off"
    ]
}

Gradle 配置方案(Kotlin DSL)

kotlin
// 创建专用配置
val mockitoAgent = configurations.create("mockitoAgent") {
    isTransitive = false
}

dependencies {
    testImplementation("org.mockito:mockito-core")
    mockitoAgent("org.mockito:mockito-core")
}

tasks.withType<Test> {
    jvmArgs = listOf(
        "-javaagent:${mockitoAgent.asPath}",
        "-Xshare:off"
    )
}

IDE 特殊配置

构建工具的配置无法自动应用到 IDE 直接运行的测试,需手动配置:

IntelliJ IDEA 配置

  1. 打开 Run/Debug Configurations
  2. 选择您的测试配置
  3. VM Options 添加:
    text
    -javaagent:/path/to/your/.m2/repository/org/mockito/mockito-core/5.17.0/mockito-core-5.17.0.jar
    -Xshare:off
  4. 路径需要替换为本地实际路径

Eclipse 配置

  1. 打开 Run Configurations
  2. 选择 JUnit 测试配置
  3. VM Arguments 添加:
    text
    -javaagent:${env_var:USERPROFILE}\.m2\repository\org\mockito\mockito-core\5.7.0\mockito-core-5.7.0.jar
    -Xshare:off
  4. 修改路径匹配您的环境变量和版本

解决方案原理解析

配置项作用必要性
-javaagent预加载Mockito代理,避免动态加载必需
-Xshare:off禁用类数据共享(CDS),解决Sharing is only supported...相关警告推荐
专用配置(mockitoAgent)隔离依赖获取路径,避免与主依赖冲突Gradle必需
IDE配置同步构建工具配置无法应用到IDE直接运行的测试可选

为什么这能解决问题?

  1. 通过 Java Agent 机制预先加载 Mockito,符合未来 JDK 安全规范
  2. 禁用类共享避免 JVM 警告干扰
  3. 构建工具统一管理路径,避免硬编码版本号

常见问题排查

  1. 配置后警告仍未消失

    • 确认是否通过 IDE 直接运行测试(需单独配置)
    • 检查 Mockito 核心 JAR 路径是否存在拼写错误
    • 更新 Mockito 至最新稳定版(5.8.0+)
  2. 构建失败:@{argLine} 报错
    移除 Maven 配置中的 @{argLine}

    xml
    <configuration>
        <argLine>
            <!-- 删除@符号 -->
            -javaagent:${org.mockito:mockito-core:jar}
            -Xshare:off
        </argLine>
    </configuration>
  3. JDK版本兼容问题
    该方案适用于:

    • OpenJDK 11+
    • Oracle JDK 17+
    • Spring Boot 2.7.x 和 3.x

最佳实践建议

  1. 固定 Mockito 版本号避免更新冲突
  2. CI/CD 环境中确保本地仓库路径正确
  3. 升级到 Mockito 5.10.0+ 获得更好的 JDK 未来版本兼容

最终效果:应用配置后,测试运行时将不再出现动态代理加载相关警告,确保项目未来在更新 JDK 后仍可正常运行 Mockito 测试。