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

Spring单元测试@Spy引发空指针问题:是否需替换为@SpyBean或其他方案?

Spring单元测试@Spy引发空指针问题:是否需替换为@SpyBean或其他方案?

这个问题其实是Mockito和Spring测试注解的分工差异导致的,咱们一步步拆解来看:

你遇到的空指针是因为@Spy是Mockito的原生注解,它只会帮你创建一个SpringParent的Spy对象,但不会触发Spring的依赖注入机制——也就是说SpringParent里用@Resource标注的SpringChild字段完全不会被赋值,自然是null,调用sc.giveChild()就会报错。

下面给你两种核心解决方案,按需选择:

方案一:换成@SpyBean(推荐在Spring上下文测试场景使用)

@SpyBean是Spring Boot Test提供的注解,它的作用是:

  • 先从Spring容器中获取SpringParent的实例(或者容器里没有就创建一个)
  • 将这个实例包装成Spy对象
  • 同时把Spy对象放回Spring容器,自动处理它的依赖注入(包括@Resource/@Autowired标注的字段)

修改后的测试类示例:

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.junit.Test;
import static org.mockito.Mockito.verify;

@SpringBootTest // 启动Spring上下文
public class InjectMock3 {

    @SpyBean
    SpringParent sp;

    @Test
    public void test() {
        sp.giveChild();
        verify(sp).giveChild();
    }
}

这样SpringParent里的SpringChild会被Spring正常注入(只要SpringChild已经注册到容器中),空指针问题直接解决。如果需要MockSpringChild,还可以配合@MockBean替换容器里的对应Bean。

方案二:用Mockito的@InjectMocks手动注入依赖(适合纯单元测试)

如果你不想启动Spring上下文,只想做轻量的Mockito单元测试,可以用@InjectMocks让Mockito自动把依赖注入到Spy对象中:

修改后的测试类示例:

import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.Mock;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class) // 用Mockito的Runner启动测试
public class InjectMock3 {

    @Mock // 创建SpringChild的Mock对象
    SpringChild sc;

    @Spy
    @InjectMocks // 把Mock的sc注入到sp的对应字段中
    SpringParent sp;

    @Test
    public void test() {
        // 给Mock的sc设置返回值
        when(sc.giveChild()).thenReturn("mock child");
        
        sp.giveChild();
        verify(sp).giveChild();
    }
}

这个方案不需要启动Spring上下文,测试速度更快,但缺点是Mockito的@InjectMocks只会做简单的字段匹配注入,不会处理Spring注解的复杂逻辑(比如@Resource的名称匹配),适合测试简单的业务逻辑场景。

选择建议

  • 如果测试需要依赖Spring容器的其他Bean(比如SpringChild本身有复杂的Spring依赖),或者要验证Spring的依赖注入逻辑,优先选@SpyBean。
  • 如果只是单独测试SpringParent的业务逻辑,不需要Spring上下文,用@Spy+@InjectMocks+@Mock的组合更轻量。

备注:内容来源于stack exchange,提问作者work-in-progress

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 08:53:07