Mockito测试中调用Mock方法时抛出空指针异常(NPE)求助
Mockito测试中调用Mock方法时抛出空指针异常(NPE)求助
我来帮你分析下问题所在,以及对应的解决方案:
问题根源
你当前的测试写法存在两个核心问题:
- 继承关系导致Mock未生效:你的
AdultDayCenterDBHandler继承自DBTemplate,但你Mock了一个独立的DBTemplate实例,并用@InjectMocks注入到测试类里。Mockito的@InjectMocks只会给被测试对象(这里是dbHandler)注入依赖,不会把父类DBTemplate的实例替换成你Mock的那个。所以当执行callDB方法时,实际走的是父类DBTemplate的真实实现,而不是你Mock的逻辑。 - 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依赖来避免真实逻辑执行。
相关产品推荐
相关产品推荐

