如何为以下包含异常处理的Spring接口代码编写JUnit测试用例
实现思路
你提供的是Spring MVC的Controller层接口,编写JUnit测试需要覆盖2个核心业务分支:
- 入参校验不通过,抛出
ValidationException的分支 - 入参校验通过,正常调用业务层返回Company对象的分支
我们可以用Spring Boot提供的@WebMvcTest注解做轻量化的Controller层测试,配合Mockito mock掉CompanyService依赖,不需要启动完整的Spring上下文。
完整测试代码示例
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import com.fasterxml.jackson.databind.ObjectMapper; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; // 仅加载对应Controller的上下文,测试轻量化 @WebMvcTest(CompanyController.class) public class CompanyControllerTest { @Autowired private MockMvc mockMvc; // Mock业务层依赖,不需要真实实现 @MockBean private CompanyService companyService; @Autowired private ObjectMapper objectMapper; @Autowired private CompanyController companyController; // 测试场景1:入参校验不通过,抛出ValidationException @Test public void testCreateCompany_withInvalidParam_throwValidationException() { // 构造Mock的Errors对象,模拟校验失败场景 Errors mockErrors = mock(Errors.class); when(mockErrors.hasErrors()).thenReturn(true); when(mockErrors.getFieldError().getDefaultMessage()).thenReturn("公司名称不能为空"); // 直接调用Controller方法验证异常抛出逻辑 ValidationException exception = assertThrows(ValidationException.class, () -> { companyController.createCompany(new Company(), mockErrors); }); assertEquals("公司名称不能为空", exception.getMessage()); } // 测试场景2:入参校验通过,正常返回Company对象 @Test public void testCreateCompany_withValidParam_returnCompany() throws Exception { // 构造合法入参 Company validCompany = new Company(); validCompany.setId(1L); validCompany.setName("测试科技有限公司"); validCompany.setAddress("北京市朝阳区"); // Mock业务层返回值 when(companyService.addCompany(any(Company.class))).thenReturn(validCompany); // 模拟发HTTP请求验证接口整体逻辑 mockMvc.perform(post("/addCompany") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(validCompany))) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(1L)) .andExpect(jsonPath("$.name").value("测试科技有限公司")) .andExpect(jsonPath("$.address").value("北京市朝阳区")); } }
注意事项
- 测试场景1是直接验证Controller的核心逻辑,不需要依赖HTTP请求发送,属于纯单元测试
- 测试场景2是验证整个HTTP链路的表现,包括参数序列化、校验注解生效等逻辑
- 如果你配置了全局异常处理器捕获
ValidationException,可以在场景1的基础上新增HTTP请求测试,验证异常返回的报文格式是否符合预期 - 代码里的校验提示信息需要和你
Company实体类上定义的JSR-380校验注解(比如@NotBlank、@Size等)的message属性对应
内容的提问来源于stack exchange,提问作者akhilvarma
相关产品推荐
相关产品推荐

