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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:54:55