含Post方法的Controller单元测试报NullPointerException排查
空指针问题根因与修复方案
你的空指针异常完全由测试类中Mockito注解的错误使用导致,控制器中this.reporterService实际为null,调用方法时自然触发NPE,具体问题和修复方式如下:
核心错误点
- 注解使用逻辑颠倒:
@InjectMocks仅用于标记待测试的目标对象(即需要被注入依赖的类),你错误地将该注解加在了依赖类ReporterService上,导致Mockito不会将reporterService作为依赖注入到控制器中。 - 手动实例化被测试类:你手动通过
new ReportEmailController()创建了控制器实例,该实例脱离Mockito容器管理,所有依赖都不会被自动注入。 - 测试变量未赋值:测试方法中调用
getIdEmailInfoRequest()后没有将返回值赋值给idEmailInfoRequest变量,该变量本身为null,即使修复依赖注入问题也会触发后续异常。 - 测试层级混乱:Controller层单元测试不需要穿透调用Repository层逻辑,直接mock Service层的返回值即可,你现在的mock逻辑写在Repository层,就算依赖注入正常也无法被Service调用到。
修复后的测试类代码
@RunWith(MockitoJUnitRunner.class) public class ReportEmailControllerTest { // 所有被依赖的下游组件统一用@Mock标记 @Mock private ReporterService reporterService; @Mock private EmailInfoRepository emailInfoRepository; // 待测试的Controller用@InjectMocks标记,不要手动new实例 @InjectMocks private ReportEmailController reportEmailController; private IdEmailInfoRequest idEmailInfoRequest; @Before public void initTestData() { idEmailInfoRequest = getIdEmailInfoRequest(); } @Test public void testIdEmailInfo_whenRequestIsValidReturnValidList() { // 构造mock返回结果 List<EmailInfoIdParams> mockServiceResult = new ArrayList<>(); EmailInfoIdParams testParam = new EmailInfoIdParams(); mockServiceResult.add(testParam); // mock Service层方法返回,匹配任意IdEmailInfoRequest类型入参 when(reporterService.getIdEmailInfo(any(IdEmailInfoRequest.class))).thenReturn(mockServiceResult); // 调用目标接口方法 ResponseEntity<EmailInfoIdResponse> response = reportEmailController.idEmailInfo("1","user",idEmailInfoRequest); // 结果断言 assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); assertNotNull(response.getBody()); assertEquals("SUCCESS", response.getBody().getStatus()); assertNotEquals(0, response.getBody().getEmailInfoIdParams().size()); } }
补充说明:如果需要单独测试
ReporterService的逻辑,单独编写Service层测试类即可:给ReporterService加@InjectMocks注解,给它依赖的EmailInfoRepository加@Mock注解,不要把不同层级的测试逻辑混在同一个测试类里。
内容的提问来源于stack exchange,提问作者Defne Sabancı
相关产品推荐
相关产品推荐

