You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data JPA中@Autowired注入Repository报空指针异常排查

Spring集成JUnit5测试时@Autowired注入Repository空指针问题

问题环境

项目基础版本与依赖如下:

  • JDK版本:9.0.4
  • pom.xml引入的核心依赖:
    • spring-context:5.3.21
    • mssql-jdbc:9.4.0.jre8
    • hibernate-core:6.1.0.Final
    • spring-data-jpa:2.7.0
    • spring-test:5.3.21(仅test作用域生效)

已完成的配置与代码

Spring核心配置

编写配置类DataConfig:

  • 类上标注注解:@Configuration、@ComponentScan("ru.tenderwin")、@EnableJpaRepositories("ru.tenderwin")
  • 类中定义3个核心Bean:
    1. SQL Server数据源:使用DriverManagerDataSource,配置驱动类、数据库连接地址、用户名、密码
    2. 实体管理器工厂:使用LocalContainerEntityManagerFactoryBean,指定Hibernate为持久化提供者、HibernateJpaVendorAdapter为JPA适配器、SQLServer2012为Hibernate方言、实体扫描路径为ru.tenderwin
    3. 事务管理器:使用JpaTransactionManager,绑定上述实体管理器工厂实例

业务代码

  • 数据库映射实体Clients:标注@Entity、@Table(schema = "Schema"),包含ID、Name、RegistrationDate三个字段
  • 数据访问接口ClientsRepository:继承CrudRepository<Clients, String>

异常现象

两种测试运行场景表现完全不一致:

  1. @Autowired注入场景(运行失败)
    编写JUnit 5测试类,类上标注@ContextConfiguration(classes = DataConfig.class)、@Transactional,使用@Autowired注入ClientsRepository类型属性clientsRepository。在@Test标注的测试方法中调用clientsRepository.findById("DE39596D-2890-4D91-BE24-000D480190AE")时,抛出java.lang.NullPointerException,报错点即为Repository方法调用行,异常堆栈显示测试方法执行时依赖注入未完成。
  2. 手动加载上下文场景(运行正常)
    不使用@Autowired注入,直接在测试方法中手动初始化AnnotationConfigApplicationContext加载DataConfig配置,通过context.getBean(ClientsRepository.class)获取Repository实例后再调用findById方法,可以正常查询到数据,控制台成功打印Optional包装的Clients实体结果。

根因分析

问题核心是JUnit 5测试类缺少Spring测试扩展声明:
@ContextConfiguration仅负责声明Spring配置加载的元数据,本身不会自动对接JUnit的测试执行模型:

  • JUnit 4环境下,需要搭配@RunWith(SpringRunner.class)才能让Spring容器接管测试类的实例化、依赖注入流程
  • JUnit 5(Jupiter)环境下,必须搭配@ExtendWith(SpringExtension.class)注解,否则测试类完全由JUnit原生机制实例化,@Autowired注解不会被任何处理器解析,注入的Repository属性默认值就是null
    手动初始化Spring上下文、手动getBean的方式,完全绕过了测试类的依赖注入流程,所以不受测试类注解缺失的影响,可以正常执行。

修复方案

在测试类上补充@ExtendWith(SpringExtension.class)注解即可,修复后的测试类示例:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;

@ExtendWith(SpringExtension.class) // 必须补充该注解,激活Spring测试支持
@ContextConfiguration(classes = DataConfig.class)
@Transactional
public class ClientsRepositoryTest {

    @Autowired
    private ClientsRepository clientsRepository;

    @Test
    void testQueryClient() {
        System.out.println(clientsRepository.findById("DE39596D-2890-4D91-BE24-000D480190AE"));
    }
}

补充提示:如果是Spring Boot项目,引入spring-boot-starter-test后使用@SpringBootTest注解会自动包含上述扩展配置,无需手动添加@ExtendWith。当前是手动集成Spring的非Boot项目,必须显式声明该扩展。

内容的提问来源于stack exchange,提问作者Лев Сабуров

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:57:22