You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为以下包含异常处理的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 01:06:01