使用MockMvc进行Spring集成测试:服务注入与仓库Mock问题
解决方案
你需要调整测试类的注解组合,因为@WebMvcTest仅会加载控制器层Bean,无法自动纳入真实服务层Bean。正确的做法是用@SpringBootTest启动完整Spring上下文,搭配@AutoConfigureMockMvc启用MockMvc,同时用@MockBean替换仓库的真实实现。
修改后的测试类示例
@SpringBootTest @AutoConfigureMockMvc public class PatientRecordControllerTests { @Autowired MockMvc mockMvc; @Autowired ObjectMapper mapper; // 用@MockBean替换真实仓库Bean,Spring会自动将该Mock注入真实的PatientRecordService @MockBean PatientRecordRepository patientRecordRepository; @Test public void createRecord_WhenDtoValid_CreateRecord() throws Exception { PatientRecordDto recordDto = PatientRecordDto.builder() .name("John Doe") .age(47) .address("New York USA") .build(); PatientRecord record = ModelMapperUtil.convertTo(recordDto, PatientRecord.class); // Mock仓库的save方法,而非服务层方法 Mockito.when(patientRecordRepository.save(Mockito.any(PatientRecord.class))).thenReturn(record); MockHttpServletRequestBuilder mockRequest = MockMvcRequestBuilders.post("/patient") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content(this.mapper.writeValueAsString(recordDto)); mockMvc.perform(mockRequest) .andExpect(status().isOk()) .andExpect(jsonPath("$", notNullValue())) .andExpect(jsonPath("$.name", is("John Doe"))); // 可选:验证仓库save方法确实被调用,确保服务逻辑执行了正确操作 Mockito.verify(patientRecordRepository, Mockito.times(1)).save(Mockito.any(PatientRecord.class)); } }
关键说明
@SpringBootTest:加载完整Spring应用上下文,让真实的PatientRecordService被创建并纳入容器。@AutoConfigureMockMvc:自动配置MockMvc,保持你原有的HTTP接口测试方式。@MockBean:告诉Spring创建PatientRecordRepository的Mock实例,替换上下文中原有的真实仓库Bean。此时真实的PatientRecordService依赖的仓库就是这个Mock,完全满足你「使用真实服务、Mock仓库,测试从控制器到服务完整逻辑」的需求。
无需使用@InjectMocks,Spring依赖注入机制会自动将Mock仓库注入真实服务Bean,无需手动处理依赖关系。
内容的提问来源于stack exchange,提问作者Matej Martincevic
相关产品推荐
相关产品推荐

