Gradle多模块测试Spring Boot代码报NoClassDefFoundError求助
问题解决:多模块Gradle项目中测试模块无法访问Spring Boot模块类的
NoClassDefFoundError问题 问题重现
项目结构:
- frog -- frog-web -- frog-test
- frog为根模块,无业务代码
- frog-web是Spring Boot模块,配置了
bootJar生成可执行Jar - frog-test依赖frog-web,测试时抛出
java.lang.NoClassDefFoundError: site/weic/grog/web/FrogWebApplication
问题原因
- Spring Boot插件滥用:根模块给所有子项目都应用了
org.springframework.boot插件,测试模块frog-test不需要该插件,插件会修改Jar生成逻辑和依赖解析规则,干扰测试类路径。 - BootJar类结构限制:
bootJar生成的可执行Jar会把类文件打包在BOOT-INF/classes目录下,普通Java编译和测试的类路径不会自动识别该路径,导致依赖模块无法找到类。
解决方案
1. 调整根模块插件应用范围
修改根模块build.gradle,仅给需要的子项目(frog-web)应用Spring Boot插件,而非全局应用:
buildscript { repositories { mavenLocal() mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:2.3.12.RELEASE") } } allprojects { apply plugin: 'java-library' group 'site.weic' version 'dev-v0.2-SNAPSHOT' sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 tasks.withType(JavaCompile) { options.encoding 'UTF-8' } repositories { mavenLocal() maven { url 'https://maven.aliyun.com/repository/public' } mavenCentral() } } subprojects { apply plugin: 'io.spring.dependency-management' dependencies { annotationProcessor 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok' implementation 'org.slf4j:slf4j-api' } dependencyManagement { dependencies { dependency "org.projectlombok:lombok:1.18.26" dependency "mysql:mysql-connector-java:8.0.23" } imports { mavenBom "org.springframework.boot:spring-boot-starter-parent:2.3.12.RELEASE" } } }
2. 修改frog-web的Jar生成配置
在frog-web的build.gradle中单独应用Spring Boot插件,同时启用普通jar任务(默认会被Spring Boot插件禁用),生成两个Jar:普通Jar供依赖使用,BootJar作为可执行包:
apply plugin: 'org.springframework.boot' bootJar { enabled true } // 启用普通jar任务,生成供其他模块依赖的标准Jar jar { enabled true } dependencies { api 'org.springframework.boot:spring-boot-starter-web' }
3. 验证测试执行
重新运行测试任务:
./gradlew :frog-test:test
此时测试模块应能正常访问frog-web的类,不再抛出NoClassDefFoundError。
额外优化(Spring Boot测试规范)
如果是测试Spring Boot应用,推荐使用@SpringBootTest注解启动应用上下文,而非直接实例化启动类:
import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest(classes = FrogWebApplication.class) public class A01Test { @Test public void a(){ System.out.println(123); } }
内容的提问来源于stack exchange,提问作者Wei
相关产品推荐
相关产品推荐

