JUnit测试中Spring ApplicationContext为null的问题求助
解决JUnit测试中ApplicationContextProvider返回null的问题
问题根源
@JdbcTest是Spring提供的切片测试注解,它只会初始化与JDBC相关的Spring组件(比如DataSource、JdbcTemplate等),不会加载完整的应用上下文。你的ApplicationContextProvider没有被纳入测试上下文的管理,导致调用getApplicationContext()时返回null。
具体解决思路
1. 确保ApplicationContextProvider被测试上下文扫描到
因为@JdbcTest默认只扫描测试类所在包和JDBC相关组件,若ApplicationContextProvider在其他包,可通过以下方式导入:
- 在测试类上添加
@Import(ApplicationContextProvider.class),直接将该类纳入测试上下文:@ExtendWith(SpringExtension.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestPropertySource(locations = "classpath:application.properties") @JdbcTest @Import(ApplicationContextProvider.class) // 导入上下文工具类 public class TestInventory { // ... 现有代码 } - 或者用
@ComponentScan指定包含ApplicationContextProvider的包路径:@ComponentScan(basePackages = "com.yourpackage.context") // 替换为实际包路径 @JdbcTest // ... 其他注解 public class TestInventory { // ... }
2. 改用全上下文测试(适合依赖较多的场景)
如果你的测试需要依赖缓存、上下文等非JDBC组件,@JdbcTest的切片范围不足以覆盖,可替换为@SpringBootTest,它会加载完整的Spring应用上下文,确保ApplicationContextProvider正常初始化:
@SpringBootTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestPropertySource(locations = "classpath:application.properties") public class TestInventory { // ... 现有代码 }
注意:全上下文测试启动速度较慢,仅在必要时使用。
3. 重构代码,避免直接依赖ApplicationContext(推荐)
通过静态工具类获取上下文的方式不符合Spring依赖注入的设计理念,耦合度高且测试不便。建议直接在数据对象中注入CacheRepository:
// 数据对象类 @Component // 确保该类被Spring管理 public class YourDataObject { private final CacheRepository cacheRepository; // 构造方法注入(推荐) public YourDataObject(CacheRepository cacheRepository) { this.cacheRepository = cacheRepository; } // 业务方法中直接使用 public void yourBusinessMethod(int currency) { Currency currencyObj = cacheRepository.getCurrencyList().stream() .filter(cur -> cur.identity() == currency) .findFirst().orElseThrow(); currencyRate = currencyObj.rate(); } }
这种方式下,Spring会自动在Web环境和测试环境中注入CacheRepository,彻底避免上下文依赖问题。
4. 手动初始化ApplicationContextProvider(应急方案)
若暂时无法重构代码,可在测试类中手动注入ApplicationContext并设置到工具类:
@ExtendWith(SpringExtension.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @TestPropertySource(locations = "classpath:application.properties") @JdbcTest public class TestInventory { @Autowired DataSource dataSource; @Autowired ApplicationContext context; @BeforeEach void setUp() { ApplicationContextProvider.setApplicationContext(context); } @Test public void testFinishedGoods() throws SQLException { // ... 测试代码 } }
注意:这种方式只是临时解决方案,长期来看还是推荐重构为依赖注入。
内容的提问来源于stack exchange,提问作者sproketboy
相关产品推荐
相关产品推荐

