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

Mockito测试中调用Mock方法时抛出空指针异常(NPE)求助

Mockito测试中调用Mock方法时抛出空指针异常(NPE)求助

我来帮你分析下问题所在,以及对应的解决方案:

问题根源

你当前的测试写法存在两个核心问题:

  1. 继承关系导致Mock未生效:你的AdultDayCenterDBHandler继承自DBTemplate,但你Mock了一个独立的DBTemplate实例,并用@InjectMocks注入到测试类里。Mockito的@InjectMocks只会给被测试对象(这里是dbHandler)注入依赖,不会把父类DBTemplate的实例替换成你Mock的那个。所以当执行callDB方法时,实际走的是父类DBTemplate的真实实现,而不是你Mock的逻辑。
  2. DBUtil未正确注入父类:你Mock了DBUtil,但这个Mock实例并没有被注入到DBTemplate中(父类的成员变量),当真实的callDB方法执行时,会尝试初始化真实的DBUtil,从而抛出NPE。

解决方案

这里给你两种可行的修复方案,选一种适合你的即可:

方案一:用@Spy Stub父类方法

直接对被测试对象dbHandler做Spy,然后Stub它继承自父类的callDB方法,彻底跳过真实的DB调用逻辑:

@ExtendWith(MockitoExtension.class)
public class AdultDayCenterDBHandlerTest {
    @Mock
    private DBUtil dbUtil;

    // 用@Spy包装被测试对象,既保留真实方法逻辑,又能Stub特定方法
    @Spy
    private AdultDayCenterDBHandler dbHandler;

    @BeforeEach
    public void setUp() {
        // 用反射把Mock的DBUtil注入到父类DBTemplate的成员变量中(如果DBTemplate依赖DBUtil的话)
        ReflectionTestUtils.setField(dbHandler, "dbUtil", dbUtil);
    }

    @Test
    public void testRetrieveAllAdultDayCenterFacilities() throws Exception {
        // Setup
        List<FacilityEntity> facilityList = generateStubData();
        ADCSearchCriteria adcSearchCriteria = generateSearchCriteria();

        // 关键:用doReturn来Stub父类的callDB方法,避免触发真实方法执行
        Mockito.doReturn(facilityList).when(dbHandler).callDB(any(SearchQuery.class));

        // 执行测试
        List<FacilityEntity> responseFromTest = dbHandler.retrieveAllAdultDayCenterFacilities(adcSearchCriteria);

        // 断言
        assertNotNull(responseFromTest);
        assertEquals(facilityList.get(0).getFacilityName(), responseFromTest.get(0).getFacilityName());
    }

    // 你的generateStubData和generateSearchCriteria方法保持不变
}

方案二:手动注入父类依赖

如果不想用Spy,也可以直接给dbHandler的父类DBTemplate注入Mock的DBUtil,确保真实的callDB方法不会触发真实的数据库连接:

@ExtendWith(MockitoExtension.class)
public class AdultDayCenterDBHandlerTest {
    @Mock
    private DBUtil dbUtil;

    @InjectMocks
    private AdultDayCenterDBHandler dbHandler;

    @BeforeEach
    public void setUp() {
        // 强制把Mock的DBUtil注入到父类DBTemplate的成员变量里
        ReflectionTestUtils.setField(dbHandler, "dbUtil", dbUtil);
        
        // 同时Stub父类的callDB方法,返回模拟数据
        Mockito.when(dbHandler.callDB(any(SearchQuery.class))).thenReturn(generateStubData());
    }

    @Test
    public void testRetrieveAllAdultDayCenterFacilities() throws Exception {
        ADCSearchCriteria adcSearchCriteria = generateSearchCriteria();
        List<FacilityEntity> responseFromTest = dbHandler.retrieveAllAdultDayCenterFacilities(adcSearchCriteria);

        assertNotNull(responseFromTest);
        assertEquals(generateStubData().get(0).getFacilityName(), responseFromTest.get(0).getFacilityName());
    }

    // 你的其他方法不变
}

额外注意点

  • 当测试继承类时,尽量不要单独Mock父类实例,而是直接操作被测试对象本身(Spy或注入依赖)。
  • 使用doReturn而非when(...).thenReturn(...)来Stub Spy对象的方法,前者不会触发真实方法的执行,能避免提前抛出NPE。
  • 如果DBTemplate的callDB是私有方法,那只能用方案二,通过注入Mock依赖来避免真实逻辑执行。
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 06:17:59