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

如何测试存在链式@Autowired依赖的方法?Mockito测试时遇空指针如何解决

空指针异常原因及修复方案

触发空指针的核心原因有两个:

  • 测试类未启用Mockito注解处理器,@InjectMocks和@Spy注解未生效,导致Class1中的autoWiredObject字段本身为null
  • 你手动实例化的AutoWiredObject内部的@Autowired依赖没有被注入,调用setAllValues时内部访问其他注入对象就会触发空指针

如果你仅需要测试Class1的getAccount逻辑,不需要验证AutoWiredObject的内部执行细节,直接Mock外部依赖是最简单的方案,修改后测试代码如下(JUnit5版本):

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;

@ExtendWith(MockitoExtension.class) // 必须加,用来激活Mockito注解
public class Class1Test {

    @InjectMocks 
    private Class1 myClass;

    @Mock // 直接Mock外部依赖,不需要使用真实实例
    private AutoWiredObject autoWiredObject;

    @Test
    public void testGetAccount() {
        // 模拟setAllValues的行为,给入参的object的value属性赋值
        doAnswer(invocation -> {
            Object1 obj = invocation.getArgument(0);
            obj.set("value", "模拟赋值"); // 可根据Object1的实际设值方法调整
            return null;
        }).when(autoWiredObject).setAllValues(any(Object1.class));

        Object1 object = myClass.getAccount(true);
        assertNotNull(object.get("value"));
    }
}

如果使用JUnit4,将@ExtendWith(MockitoExtension.class)替换为@RunWith(MockitoJUnitRunner.class)即可。

多层Autowired依赖链的最优单元测试方案
  • 纯单元测试优先走隔离方案:被测类的所有外部依赖全部用@Mock替换,不需要引入依赖的真实实现,也不需要处理依赖的依赖问题,只需要Mock依赖对外暴露的方法的行为即可,测试执行速度快,且不会受依赖内部逻辑变动的影响
  • 如果需要连带测试依赖的内部逻辑,属于集成测试范畴,可以配合Spring Test的@SpringBootTest注解启动Spring上下文自动注入全链路依赖,但启动上下文耗时久,不适用于快速执行的单元测试
  • 如果一定要使用@Spy调用依赖的真实方法,需要手动给Spy实例的内部Autowired字段赋值,或配合Spring Test注入Spy实例,复杂度远高于直接Mock依赖
测试autowiredObject.setAllValues(object)逻辑的简便方式
  • 如果你只需要验证Class1确实调用了该方法,不需要验证赋值逻辑,直接使用Mockito的verify方法即可,不需要模拟方法行为:
@Test
public void testSetAllValuesInvoke() {
    Object1 object = myClass.getAccount(true);
    // 验证setAllValues被调用了1次,且入参就是返回的object实例
    verify(autoWiredObject, times(1)).setAllValues(object);
}
  • 如果你要验证setAllValues本身的逻辑,单独编写AutoWiredObject的单元测试即可,不需要和Class1的测试耦合,每个类的单元测试仅负责验证自身逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 20:15:05