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

Spring Boot+Mockito测试:如何验证City查询‘未找到’场景?

解决方案

1. 修正单元测试,传入合法CityId参数验证未找到场景

你的测试代码错误传入了字符串"notfound",但cityService.getCity()要求的是CityId对象。直接构造一个不存在的CityId实例传入,结合已mock的cityRepository.findById()返回Optional.empty(),就能触发业务方法的未找到逻辑:

@Test
public void testGetCityNotFound() throws Exception {
    // Mock仓库返回空Optional,模拟未找到数据
    Mockito.when(cityRepository.findById(Mockito.any(CityId.class))).thenReturn(Optional.empty());

    // 构造一个不存在的CityId实例(填入业务中不存在的国家码和邮编即可)
    CityId nonExistentCityId = new CityId("XX", "99999");
    
    // 验证业务方法返回null
    assertEquals(null, cityService.getCity(nonExistentCityId));
}

这里用Mockito.any(CityId.class)比any()更精准,明确匹配CityId类型参数。只要该CityId在mock的仓库中不存在,就会触发NoSuchElementException,最终业务方法返回null。

2. 修改业务方法使其返回"not found"字符串

当前业务方法返回类型是City,直接返回字符串会编译报错,推荐两种合理处理方式:

方式一:返回Optional<City>(兼顾类型安全与空值处理)

调整方法返回类型为Optional<City>,保留类型安全的同时,让调用方可以灵活处理空值场景:

public Optional<City> getCity(CityId cityId) {
    try {
        return cityRepository.findById(cityId);
    } catch(IllegalArgumentException e) {
        e.printStackTrace();
        return Optional.empty();
    }
}

测试时验证返回Optional.empty(),后续在调用方(如控制器)判断:若为空则返回"not found"字符串。

方式二:抛出自定义异常(符合RESTful规范)

业务方法抛出自定义异常,在控制器层统一捕获并返回"not found"响应,这是Spring Boot项目的最佳实践:

public City getCity(CityId cityId) {
    return cityRepository.findById(cityId)
            .orElseThrow(() -> new CityNotFoundException("not found"));
}

// 自定义异常类
public class CityNotFoundException extends RuntimeException {
    public CityNotFoundException(String message) {
        super(message);
    }
}

然后在全局异常处理器中捕获该异常:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(CityNotFoundException.class)
    public ResponseEntity<String> handleCityNotFound(CityNotFoundException e) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
    }
}

不推荐的方式:修改返回类型为Object

如果硬要让业务方法直接返回字符串,只能将返回类型改为Object,但这会丢失类型检查,不建议在生产代码中使用:

public Object getCity(CityId cityId) {
    try {
        return cityRepository.findById(cityId).get();
    } catch(NoSuchElementException | IllegalArgumentException e) {
        e.printStackTrace();
        return "not found";
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 21:13:23