Spring Boot测试环境无法创建应用上下文问题求助
问题背景
- 基于Spring Boot 2.6.6开发无数据库的REST中间层应用,正常启动无异常,但执行测试套件时无法创建应用上下文
- 初始报错:
java.lang.StackOverflowError,栈信息重复ch.qos.logback.classic.spi.ThrowableProxy.<init> - 定位到问题源于一个基于Spring Boot 2.1.6.RELEASE的权限认证Maven依赖(使用AOP)
- 关闭Logback后出现
java.lang.IllegalStateException: Failed to unwrap proxied object异常 - 开启Debug日志后触发
javax.validation.NoProviderFoundException,提示缺少Jakarta Bean Validation提供者,添加hibernate-validator和spring-boot-starter-validator依赖无效 - 已尝试的无效方案:调整
@SpringBootTest配置、更换AOP依赖、启用@EnableAspectJAutoProxy、代理解包方案
解决方案
1. 正确配置Hibernate Validator解决NoProviderFoundException
Spring Boot 2.6.x依赖Jakarta Bean Validation 2.0+(对应Hibernate Validator 6.x),而旧版Spring Boot 2.1.x依赖Java EE体系的Bean Validation,跨版本依赖冲突会导致提供者无法加载,按以下步骤处理:
- 排除冲突依赖:在权限认证依赖中排除旧版validation相关依赖,避免与Spring Boot 2.6.x的依赖冲突:
<dependency> <groupId>你的权限认证依赖groupId</groupId> <artifactId>你的权限认证依赖artifactId</artifactId> <version>对应版本</version> <exclusions> <exclusion> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> </exclusion> <exclusion> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> </exclusion> </exclusions> </dependency> - 引入兼容的官方starter:添加Spring Boot官方的validation starter,版本由Spring Boot parent自动管理,确保兼容性:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> - 强制锁定API版本:如果仍存在依赖冲突,在
dependencyManagement中明确指定Jakarta版本的validation-api:<dependencyManagement> <dependencies> <dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>2.0.2</version> </dependency> </dependencies> </dependencyManagement> - 验证类路径:执行
mvn dependency:tree命令检查,确保类路径中只有jakarta.validation:jakarta.validation-api和org.hibernate.validator:hibernate-validator,无旧版javax.validation:validation-api。
2. 栈溢出与代理解包异常的整体解决方案
解决Logback栈溢出问题
该问题是异常被AOP代理反复捕获包装,导致Logback生成ThrowableProxy时递归调用,处理方式:
- 调整AOP切面逻辑:检查权限认证AOP的
@Around或@AfterThrowing通知,避免对异常进行重复包装,确保异常仅被处理一次。 - 限制Logback异常栈深度:在
logback-spring.xml中配置异常栈打印的最大深度,避免递归解析:<configuration> <!-- 其他配置 --> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%ex{5}</pattern> <!-- %ex{5} 限制仅打印5层异常栈 --> </encoder> </appender> </configuration>
解决代理解包异常
Failed to unwrap proxied object是跨Spring版本的代理类不兼容导致,处理方式:
- 强制使用CGLIB代理并暴露代理:在启动类添加
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true),使用CGLIB代理替代JDK动态代理,同时允许Spring暴露代理对象。 - 精简测试上下文:在
@SpringBootTest中排除权限认证相关的自动配置类,减少测试时加载的Bean:@SpringBootTest(exclude = {AuthAutoConfiguration.class}) public class YourTestClass { // 测试代码 } - 升级权限认证依赖版本:如果可行,将权限认证依赖升级到与Spring Boot 2.6.x兼容的版本(建议2.5.x及以上),从根源解决跨版本的代理、依赖冲突问题。
内容的提问来源于stack exchange,提问作者BT_Code
相关产品推荐
相关产品推荐

