Byte Buddy与Mockito类路径不一致及Spring Bean创建异常求助
初始错误信息
Caused by: org.mockito.exceptions.base.MockitoInitializationException:
It seems like you are running Mockito with an incomplete or inconsistent class path. Byte Buddy could not be loaded.
依赖树
[INFO] +- org.junit.jupiter:junit-jupiter:jar:5.9.1:test [INFO] | +- org.junit.jupiter:junit-jupiter-api:jar:5.9.1:test [INFO] | | +- org.opentest4j:opentest4j:jar:1.2.0:test [INFO] | | \- org.junit.platform:junit-platform-commons:jar:1.9.1:test [INFO] | +- org.junit.jupiter:junit-jupiter-params:jar:5.9.1:test [INFO] | \- org.junit.jupiter:junit-jupiter-engine:jar:5.9.1:test [INFO] +- org.junit.vintage:junit-vintage-engine:jar:5.9.1:test [INFO] | +- org.junit.platform:junit-platform-engine:jar:1.9.1:test [INFO] | +- junit:junit:jar:4.13.2:test [INFO] | | \- org.hamcrest:hamcrest-core:jar:1.3:test [INFO] | \- org.apiguardian:apiguardian-api:jar:1.1.2:test [INFO] +- org.hamcrest:hamcrest:jar:2.2:test [INFO] +- org.mockito:mockito-inline:jar:4.11.0:test [INFO] | \- org.mockito:mockito-core:jar:4.11.0:test [INFO] | +- net.bytebuddy:byte-buddy-agent:jar:1.12.19:test [INFO] | \- org.objenesis:objenesis:jar:3.3:test [INFO] +- org.mockito:mockito-junit-jupiter:jar:4.11.0:test [INFO] +- org.springframework:spring-test:jar:5.3.9:test [INFO] +- org.hibernate:hibernate-core:jar:5.4.32.Final:compile [INFO] | +- org.jboss.logging:jboss-logging:jar:3.4.1.Final:compile [INFO] | +- javax.persistence:javax.persistence-api:jar:2.2:compile [INFO] | +- org.javassist:javassist:jar:3.27.0-GA:compile [INFO] | +- net.bytebuddy:byte-buddy:jar:1.10.22:compile
Surefire插件配置
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> </plugin>
临时解决后的新错误
添加以下test scope的ByteBuddy依赖后:
<dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.12.19</version> <scope>test</scope> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.12.19</version> <scope>test</scope> </dependency>
出现新错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/applicationContext-jpa.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: net/bytebuddy/NamingStrategy$SuffixingRandom$BaseNameResolver
EntityManagerFactory配置
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="persistenceUnitName" value="myPU" /> <property name="jpaProperties"> <value> hibernate.dialect=${hibernate.dialect} hibernate.query.substitutions=${hibernate.substitutions} hibernate.cache.use_second_level_cache=${hibernate.use.secondLevelCache} hibernate.cache.provider_class=${hibernate.cacheProvider.class} hibernate.show_sql=${hibernate.cacheProvider.show.sql} </value> </property> </bean>
问题根源与解决办法
为啥会出这问题
核心是ByteBuddy版本不统一:
- Hibernate 5.4.32.Final自带的是
byte-buddy:1.10.22(编译依赖,测试运行时也会加载) - Mockito 4.11.0需要的是
byte-buddy:1.12.19(测试依赖,仅测试阶段生效)
手动添加test scope的1.12.19版本后,测试运行时类路径里同时存在两个版本的ByteBuddy。Maven会优先加载路径更近的依赖(这里test依赖优先级更高),导致Hibernate启动时加载了1.12.19版本,但该版本中NamingStrategy$SuffixingRandom$BaseNameResolver类的结构与Hibernate预期的1.10.22版本不兼容,直接抛出找不到类的错误。
两种解决思路
思路1:统一使用Mockito需要的ByteBuddy版本
在pom.xml的dependencyManagement中强制所有依赖使用同一ByteBuddy版本(Hibernate 5.4.x兼容1.12.x版本):
<dependencyManagement> <dependencies> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.12.19</version> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.12.19</version> </dependency> </dependencies> </dependencyManagement>
之后删除之前手动添加的两个test scope的ByteBuddy依赖,Mockito和Hibernate会自动使用这个统一版本。
思路2:降级Mockito适配Hibernate的ByteBuddy版本
Mockito 3.x系列兼容ByteBuddy 1.10.x,将Mockito依赖版本改为3.12.4:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.12.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>3.12.4</version> <scope>test</scope> </dependency>
这种方式无需修改ByteBuddy依赖,直接使用Hibernate自带的1.10.22版本即可。
验证步骤
执行mvn dependency:tree检查ByteBuddy版本是否统一,再运行测试确认问题解决。
内容的提问来源于stack exchange,提问作者mop

