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

@Value注入的lateinit变量测试调用自定义Bean时未初始化问题

问题原因
  • 你测试代码中的RedisSubscriptionStore实例是手动调用构造方法val sut = RedisSubscriptionStore(redisTemplate, objectMapper)创建的,没有交给Spring IoC容器管理。
  • @Value、@Autowired这类Spring注解的注入逻辑仅对容器创建的Bean生效,自行new的对象不会被Spring做任何属性注入处理,因此defaultPackageForFCMInstance不会被初始化。
  • 测试类直接加@Value能拿到值,是因为@SpringBootTest修饰的测试类本身属于Spring容器管理的Bean,Spring会自动处理类内的所有注入注解。
解决方案

方案1:直接注入RedisSubscriptionStore实例(最推荐)

将测试类中手动创建的sut改为Spring自动注入即可,修改后代码如下:

@SpringBootTest()
@Tag("integration")
internal class RedisSubscriptionStoreIntegTest @Autowired constructor(
    val objectMapper: ObjectMapper,
    val redisTemplate: RedisTemplate<String, String>,
    val sut: RedisSubscriptionStore // 直接注入容器管理的Bean
) {

    @Test
    fun `return 200 when updating subscription`() {
        sut.updateSubscription(updatedSub)
        //Assert
        val newlyUpdatedSub = getSubscription(updatedSub.peerID)
        Assertions.assertEquals(updatedSub, newlyUpdatedSub)
    }
}

该方案拿到的sut和项目正式运行时的实例逻辑完全一致,所有注解都会被正确处理。

方案2:手动给属性赋值

如果确实需要手动创建sut实例,可以把测试类拿到的配置值直接赋值给sut的对应属性:

@SpringBootTest()
@Tag("integration")
internal class RedisSubscriptionStoreIntegTest @Autowired constructor(
    val objectMapper: ObjectMapper,
    val redisTemplate: RedisTemplate<String, String>
) {
     @Value("${default.package}")
     lateinit var defaultPackageForFCMInstance: String

     val sut = RedisSubscriptionStore(redisTemplate, objectMapper)

     @BeforeEach
     fun init() {
         // 手动给sut的属性赋值
         sut.defaultPackageForFCMInstance = this.defaultPackageForFCMInstance
     }
}

方案3:手动触发Spring注入逻辑

如果需要模拟Spring的完整注入处理,可以用Spring提供的AutowireCapableBeanFactory处理自行创建的对象:

@SpringBootTest()
@Tag("integration")
internal class RedisSubscriptionStoreIntegTest @Autowired constructor(
    val objectMapper: ObjectMapper,
    val redisTemplate: RedisTemplate<String, String>,
    val beanFactory: AutowireCapableBeanFactory
) {
     val sut = RedisSubscriptionStore(redisTemplate, objectMapper)

     @BeforeEach
     fun init() {
         // 触发Spring对手动创建对象的注入逻辑
         beanFactory.autowireBean(sut)
     }
}

内容的提问来源于stack exchange,提问作者GeoGoeG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 16:15:04