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

Spring MockMvc如何测试REST Controller中ID为空的DELETE请求?

问题分析

你遇到的500错误核心原因是:当传入空字符串作为id时,MockMvc构造的请求URL变成了/api/wallet/,而你的控制器只映射了/api/wallet/{id}这个带路径变量的DELETE接口。Spring找不到匹配的处理方法,抛出HttpRequestMethodNotSupportedException,如果没有全局异常处理兜底,就会返回500状态码,而不是预期的参数校验错误。

下面针对你要测试的两个场景,给出具体的解决方案:


场景1:测试ID为空字符串(路径变量存在但为空)

要触发参数绑定错误(空字符串无法转换为Long类型),你需要构造包含空路径段的请求,同时确保Spring能匹配到控制器方法。另外注意:DELETE请求通常不需要请求体,测试代码里可以去掉冗余的content()相关逻辑:

@Test
void shouldThrowBadRequestWhenWalletIdIsEmptyString() throws Exception {
    // 构造URL为/api/wallet/(空路径段作为id)
    ResultActions result = mockMvc.perform(delete("/api/wallet/{id}", "")
            .contentType(MediaType.APPLICATION_JSON));
    
    // 空字符串转Long失败,预期返回400 Bad Request
    result.andExpect(status().isBadRequest());
}

如果这个请求还是匹配不到控制器方法,可以调整Spring的路径匹配配置,允许空路径变量:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseTrailingSlashMatch(true);
    }
}

场景2:测试ID等于0

这个场景很直接,构造路径变量为0的请求即可,此时会触发@Min(1)的校验规则,返回400错误:

@Test
void shouldThrowBadRequestWhenWalletIdIsZero() throws Exception {
    ResultActions result = mockMvc.perform(delete("/api/wallet/{id}", 0)
            .contentType(MediaType.APPLICATION_JSON));
    
    result.andExpect(status().isBadRequest())
          // 可选:如果有全局异常处理返回校验信息,可以额外断言错误内容
          .andExpect(jsonPath("$.message").value("must be greater than or equal to 1"));
}

额外优化建议

  1. 移除冗余请求体:你的DELETE接口没有接收请求体的参数,测试代码里完全可以去掉content()和objectMapper相关的逻辑,简化测试。
  2. 添加全局异常处理:统一处理各类异常,让状态码更符合REST规范,比如给HttpRequestMethodNotSupportedException返回405,给校验异常返回400:
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<String> handleMethodNotAllowed(HttpRequestMethodNotSupportedException ex) {
        return new ResponseEntity<>("请求方法不支持", HttpStatus.METHOD_NOT_ALLOWED);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<Map<String, String>> handleConstraintViolation(ConstraintViolationException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getConstraintViolations().forEach(violation -> {
            String field = violation.getPropertyPath().toString();
            errors.put(field, violation.getMessage());
        });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(TypeMismatchException.class)
    public ResponseEntity<String> handleTypeMismatch(TypeMismatchException ex) {
        return new ResponseEntity<>("参数类型无效", HttpStatus.BAD_REQUEST);
    }
}

这样调整后,无论是方法不支持还是参数错误,都会返回符合预期的状态码,测试结果也会更准确。

内容的提问来源于stack exchange,提问作者RobertoJavaDev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 13:19:09