Spring Controller Mockito测试出现NullPointerException问题求助
Spring Controller测试:搞定MockMvc空指针与TeacherService注入问题
先解决MockMvc空指针
你的测试类里MockMvc mvc字段没加@Autowired注解,@AutoConfigureMockMvc会自动创建MockMvc实例,但得让Spring把它注入到测试类里才行。直接给mvc加上@Autowired就行。另外你同时加了@ExtendWith(MockitoExtension.class)和@ExtendWith(SpringExtension.class),其实SpringExtension已经包含了Mockito的支持,删掉MockitoExtension的注解即可,或者换成@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)配合@AutoConfigureMockMvc,配置更简洁。
TeacherService的注入是对的
@MockBean用法没问题,它会在Spring测试上下文里把真实的TeacherService替换成Mock对象,Controller能正常注入这个Mock,不用调整。
测试类里还有几个坑要踩平
- 删掉
@InjectMocks private TeacherForm teacherForm;:TeacherForm是表单DTO,不需要依赖注入,这个注解会让teacherForm变成null,后面调用getId()直接触发空指针。表单数据是通过请求参数传递的,测试里已经用.param()传值,无需提前实例化。 - 修正Mock的返回值:你的Controller里
teacherService.findById()返回的是Optional<Teacher>,之前返回null会导致调用isPresent()时抛出异常,应该改成返回Optional.empty(),用anyLong()匹配任意ID更灵活:when(teacherService.findById(anyLong())).thenReturn(Optional.empty()); - 想更轻量的话,用
@WebMvcTest(TeacherController.class)替代@ExtendWith和@AutoConfigureMockMvc,这个注解只会加载Controller相关的Bean,测试启动更快。
修正后的完整测试代码
@ExtendWith(SpringExtension.class) @AutoConfigureMockMvc public class TeacherControllerMockTest { @Autowired private MockMvc mvc; @MockBean private TeacherService teacherService; @Captor private ArgumentCaptor<Teacher> teacherCaptor; @Test void addTeacherPostNonExistingTeacher() throws Exception { // Mock教师不存在的场景 when(teacherService.findById(anyLong())).thenReturn(Optional.empty()); mvc.perform(post("/addTeacher") .param("firstName", "Anne-Marie") .param("lastName", "Kermarrec") ) .andExpect(status().is3xxRedirection()) .andReturn(); verify(teacherService, atLeastOnce()).saveTeacher(teacherCaptor.capture()); Teacher capturedTeacher = teacherCaptor.getValue(); assertEquals("Kermarrec", capturedTeacher.getLastName()); } }
可选轻量配置(用@WebMvcTest)
@WebMvcTest(TeacherController.class) public class TeacherControllerMockTest { @Autowired private MockMvc mvc; @MockBean private TeacherService teacherService; @Captor private ArgumentCaptor<Teacher> teacherCaptor; // 测试方法和上面一致 }
最后提醒:你的Controller里的TeacherService得是Spring管理的(比如用@Autowired或构造注入),不然Mock对象没法正常注入进去。
内容的提问来源于stack exchange,提问作者snsdtiti
相关产品推荐
相关产品推荐

