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

Spring Boot JUnit5单元测试:Service层返回Null但HTTP状态码为2XX

JUnit5测试Spring Boot服务时返回体为Null但状态码2XX的解决方法

核心问题是未正确Mock Service依赖的Repository层方法,且部分测试的Stub顺序错误,导致Service执行时无法获取预期数据,最终返回体为Null。以下是具体问题分析和修正方案:


问题拆解

  1. 错误Mock了Service自身方法:在findAll测试中,你Stub的是garbageTypeService.findAll(),但Service的findAll实际依赖garbageTypeRepository.findAll(),应该Mock Repository的方法而非Service自己的方法。
  2. Stub顺序颠倒:findAll测试中先调用了Service方法,之后才设置Mock返回值,此时方法已执行完毕,Stub不会生效。必须先Stub Repository方法,再调用Service方法。
  3. 未Stub其他Repository操作:getGarbage_typeById和createGarbage_type测试中,没有Mock对应的repository.findById()和repository.save()方法,导致Service无法获取数据,返回体为Null。

修正后的完整测试代码

@ExtendWith(MockitoExtension.class)
class GarbageTypeServiceTest {

    @InjectMocks
    private GarbageTypeService garbageTypeService;
    @Mock
    private GarbageTypeRepository garbageTypeRepository;

    Garbage_type g1 = new Garbage_type(0, "寶特瓶", 0.012);
    Garbage_type g2 = new Garbage_type(1, "鐵鋁罐", 0.2);
    Garbage_type g3 = new Garbage_type(2, "紙類", 0.003);
    Garbage_type g4 = new Garbage_type(3, "鋁箔包", 0.5);

    @Test
    void getGarbage_typeById() throws JsonProcessingException {
        // Mock Repository的findById方法,返回预期数据
        Mockito.when(garbageTypeRepository.findById(0L)).thenReturn(Optional.of(g1));

        ResponseEntity<Garbage_type> _ResGarbageType = garbageTypeService.getGarbage_typeById(0);
        Garbage_type _garbageType = _ResGarbageType.getBody();
        String jsonInput = this.convertToJson(g1);
        String jsonOutput = this.convertToJson(_garbageType);

        System.out.println("Status Code :" + _ResGarbageType.getStatusCode());
        System.out.println("Input:" + jsonInput);
        System.out.println("Output:" + jsonOutput);
        assertThat(jsonInput).isEqualTo(jsonOutput);
    }

    @Test
    void createGarbage_type() throws JsonProcessingException {
        Garbage_type g5 = new Garbage_type(4, "廚餘", 0.15);
        // Mock Repository的save方法,返回传入的对象
        Mockito.when(garbageTypeRepository.save(Mockito.any(Garbage_type.class))).thenReturn(g5);

        ResponseEntity<Garbage_type> _ResGarbageType = garbageTypeService.createGarbage_type(g5);
        Garbage_type _garbageType = _ResGarbageType.getBody();
        String jsonInput = this.convertToJson(g5);
        String jsonOutput = this.convertToJson(_garbageType);

        System.out.println("Status Code :" + _ResGarbageType.getStatusCode());
        System.out.println("Input:" + jsonInput);
        System.out.println("Output:" + jsonOutput);
        assertThat(jsonInput).isEqualTo(jsonOutput);
    }

    @Test
    void findAll() throws JsonProcessingException {
        List<Garbage_type> _garbageTypeList = Arrays.asList(g1, g2, g3, g4);
        // 先Mock Repository的findAll方法,返回预期列表
        Mockito.when(garbageTypeRepository.findAll()).thenReturn(_garbageTypeList);

        // 再调用Service方法
        List<Garbage_type> _ResGarbageType = garbageTypeService.findAll();

        String jsonInput = this.convertToJson(_ResGarbageType);
        String jsonOutput = this.convertToJson(_garbageTypeList);

        System.out.println("Input:" + jsonInput);
        System.out.println("Output:" + jsonOutput);
        assertThat(jsonInput).isEqualTo(jsonOutput);
    }

    @Test
    void findByGarbageTypeId() {
        // 同理,需Mock对应的Repository方法
    }

    private String convertToJson(Object obj) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(obj);
    }
}

额外注意事项

  • 检查GarbageTypeService的实现逻辑:比如getGarbage_typeById是否正确处理了repository.findById返回的Optional,若Optional为空时是否仍返回2XX状态码但体为Null,这可能是状态码正常但返回体Null的另一个原因。
  • 若JSON字符串比较失败,建议给Garbage_type类实现equals和hashCode,或配置ObjectMapper忽略字段顺序,避免因序列化顺序差异导致断言失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:09:34