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

如何为含多参数(布尔参数)的GET API编写JUnit测试用例?

如何为带布尔参数的GET API编写JUnit测试用例?

针对你这个带有可选参数的GET API,咱们得把所有代码分支都覆盖到才能保证测试的完整性。这里我会用Spring Boot的@WebMvcTest来做Controller层的单元测试,同时Mock掉brandService,这样就不用依赖真实的数据库或业务逻辑啦。

测试思路

你的API里有这些关键分支需要覆盖:

  • 默认参数场景(start、limit、show_rejected都不传)
  • show_rejected为true/false的两种业务逻辑
  • limit在合法范围(1-250)和非法范围(<1或>250)的情况
  • 有数据返回和无数据返回的场景
  • 业务层抛出异常的异常处理场景

完整测试代码示例

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 org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;

import java.util.ArrayList;
import java.util.List;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

// 替换成你的Controller实际类名
@WebMvcTest(BrandController.class)
public class BrandControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private BrandService brandService; // Mock业务层,避免依赖真实实现

    // 测试1:所有参数都不传,使用默认值(start=0, limit=50, show_rejected=false)
    @Test
    public void listBrands_withDefaultParams_returnsActiveBrands() throws Exception {
        // 模拟业务层返回分页数据
        Page<Brand> mockPage = new PageImpl<>(List.of(new Brand()));
        when(brandService.findAllActiveBrands(0, 50)).thenReturn(mockPage);

        mockMvc.perform(get("/api/brand/multi-get")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(ErrorCode.error_0))
                .andExpect(jsonPath("$.message").value("Brand list"))
                .andExpect(jsonPath("$.data").isNotEmpty());
    }

    // 测试2:show_rejected=true,返回所有品牌(包括已拒绝的)
    @Test
    public void listBrands_showRejectedTrue_returnsAllBrands() throws Exception {
        List<Brand> mockBrands = List.of(new Brand(), new Brand());
        when(brandService.findAllBrands(0, 50)).thenReturn(mockBrands);

        mockMvc.perform(get("/api/brand/multi-get")
                        .param("show_rejected", "true")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(ErrorCode.error_0))
                .andExpect(jsonPath("$.data.length()").value(2));
    }

    // 测试3:show_rejected=true但无数据返回
    @Test
    public void listBrands_showRejectedTrue_noData_returnsEmptyList() throws Exception {
        when(brandService.findAllBrands(0, 50)).thenReturn(new ArrayList<>());

        mockMvc.perform(get("/api/brand/multi-get")
                        .param("show_rejected", "true")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.data").isEmpty());
    }

    // 测试4:limit小于1,返回错误码1104
    @Test
    public void listBrands_limitLessThan1_returnsError1104() throws Exception {
        mockMvc.perform(get("/api/brand/multi-get")
                        .param("limit", "0")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(ErrorCode.error_1104))
                .andExpect(jsonPath("$.message").value(ErrorCode.error_msg1104));
    }

    // 测试5:limit大于250,返回错误码1104
    @Test
    public void listBrands_limitGreaterThan250_returnsError1104() throws Exception {
        mockMvc.perform(get("/api/brand/multi-get")
                        .param("limit", "251")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(ErrorCode.error_1104));
    }

    // 测试6:自定义start和limit,show_rejected=false
    @Test
    public void listBrands_customStartAndLimit_returnsActiveBrands() throws Exception {
        Page<Brand> mockPage = new PageImpl<>(List.of(new Brand()));
        when(brandService.findAllActiveBrands(10, 100)).thenReturn(mockPage);

        mockMvc.perform(get("/api/brand/multi-get")
                        .param("start", "10")
                        .param("limit", "100")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.data").isNotEmpty());
    }

    // 测试7:业务层抛出异常,验证异常处理逻辑
    @Test
    public void listBrands_serviceThrowsException_returnsDefaultResponse() throws Exception {
        when(brandService.findAllActiveBrands(0, 50)).thenThrow(new RuntimeException("Test exception"));

        mockMvc.perform(get("/api/brand/multi-get")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED))
                .andExpect(status().isOk())
                // 你的代码里异常时会返回空的responseDTO,这里根据实际返回值调整断言
                .andExpect(jsonPath("$.code").isEmpty());
    }
}

一些注意点

  • 记得把代码里的BrandController、BrandService、Brand替换成你实际的类名
  • @MockBean会帮你创建一个Mock的业务层实例,你可以用when()方法来指定它的返回值或抛出异常
  • 因为你的API声明了consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,所以测试时要设置contentType为对应的类型
  • 每个测试用例都对应了一个代码分支,这样能保证你的API逻辑都被验证到

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:19:18