Spock测试中@Autowired无法注入JpaRepository问题排查
问题根源分析&解决方案
你遇到的依赖注入失败问题,主要是测试配置、文件类型、依赖冲突这几个方面叠加导致的,咱们一步步拆解解决:
1. Spock测试文件类型完全错了!
Spock是基于Groovy的测试框架,你的AccountRepositorySpec如果是.java文件(从Surefire插件的<include>**/*Spec.java</include>能看出来),根本没法被Spock正确识别。Java类硬继承Groovy的Specification,Spring根本没法正常初始化测试上下文,依赖自然注入失败。
解决:
把AccountRepositorySpec.java重命名为AccountRepositorySpec.groovy,同时调整Surefire插件的配置:
<includes> <include>**/*Spec.groovy</include> <include>**/*Test.java</include> </includes>
2. 测试注解冲突+冗余
你同时用了@DataJpaTest和@SpringBootTest,这俩注解的作用完全重叠:
@DataJpaTest是专门给JPA仓库用的切片测试,会自动配置轻量级的JPA上下文;@SpringBootTest是加载完整的Spring应用上下文,同时用会导致上下文加载混乱,Bean没法正常初始化。
另外@ContextConfiguration也是多余的,上面俩注解已经自动处理上下文配置了。
解决:
如果只是测试JPA仓库,只用@DataJpaTest就行:
@DataJpaTest class AccountRepositorySpec extends Specification { @Autowired private AccountRepository accountRepository; def "Verify repository is injected"(){ expect: accountRepository != null 1 == 1 } }
如果要测试Service/Controller这类需要完整上下文的组件,再单独用@SpringBootTest,别和@DataJpaTest混用。
3. pom.xml依赖重复到离谱
你重复引入了spring-boot-starter-test、junit,还有多余的spring-boot-test,这些重复依赖会导致版本冲突,直接破坏Spring测试框架的初始化流程。
解决:
清理后的dependencies部分应该是这样(去掉重复,统一版本):
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <!-- 排除自带的JUnit,避免和手动引入的版本冲突 --> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-core</artifactId> <version>1.1-groovy-2.4</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies>
4. Maven Surefire插件的分组配置坑
你加了<groups>com.microservices.accountservice.UnitTest</groups>,这个配置会只运行标记了该组的测试。如果你的测试类没加@Category(UnitTest.class)注解,测试运行时根本不会触发Spring上下文的加载流程,依赖自然是null。
解决:
- 如果你不需要按分组运行,直接删掉
<groups>配置; - 如果要保留分组,给测试类加上对应注解:
同时确保@Category(com.microservices.accountservice.UnitTest.class) @DataJpaTest class AccountRepositorySpec extends Specification { // ...测试代码 }UnitTest这个类确实存在。
最后验证一下上下文扫描
确保你的MainSpring主类所在的包是项目根包,AccountRepository在它的子包下(Spring会自动扫描主包及子包的Bean)。如果Repository不在扫描范围内,给主类加@EnableJpaRepositories(basePackages = "你的Repository所在包路径")手动指定扫描路径。
内容的提问来源于stack exchange,提问作者maciejka

