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

JUnit结合Spring Rest Docs测试失败:接口返回数据不符问题

问题分析

你遇到的java.lang.AssertionError: []: Expected 2 values but got 0错误,核心原因是你用@MockBean注解了ProductService,但没有给这个Mock对象指定方法的返回逻辑。

在Spring的@WebMvcTest测试场景中,@MockBean会把容器里真实的ProductServiceImpl替换成一个Mockito生成的Mock实例。默认情况下,Mock对象的所有方法调用都会返回对应类型的默认值——比如List类型就会返回空列表,这就是为什么你的测试里接口实际返回空数组,和你预先准备的两个产品数据不匹配,最终导致断言失败。

解决方案

你只需要在测试的初始化阶段,用Mockito的when(...).thenReturn(...)语法,明确指定当调用productService.getAllProduct()时,返回你预先准备好的products列表即可。

修改后的测试类代码
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
@WebMvcTest
public class ProductControllerTest {
    @Autowired
    private WebApplicationContext webApplicationContext;
    @MockBean
    private ProductService productService;
    private MockMvc mockMvc;
    List<Product> products = null;

    @BeforeEach
    public void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider documentationContextProvider) {
        this.mockMvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                .apply(MockMvcRestDocumentation.documentationConfiguration(documentationContextProvider))
                .build();
        products = getProducts();
        // 关键:给Mock的Service指定方法返回值
        Mockito.when(productService.getAllProduct()).thenReturn(products);
    }

    @Test
    public void getAllProducts() throws Exception { // 建议修改方法名,更贴合业务语义
        String expectedProduct = new ObjectMapper().writeValueAsString(products);
        MvcResult result = mockMvc.perform(get("/products")
                        .contentType(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(status().isOk())
                .andExpect(content().json(expectedProduct))
                .andReturn();
        String actualProduct = result.getResponse().getContentAsString();
        Assertions.assertEquals(expectedProduct, actualProduct);
    }

    private List<Product> getProducts() {
        Product product_1 = new Product();
        product_1.setProductId(1001);
        product_1.setProductName("Penguin-ears");
        product_1.setNumberOfUnitInCartoon(20);
        product_1.setPriceOfCartoon(175.00);
        product_1.setUrlOfImage("https://i.ibb.co/pLdM7FL/shutterstock-306427430-scaled.jpg");
        Product product_2 = new Product();
        product_2.setProductId(1002);
        product_2.setProductName("Horseshoe");
        product_2.setNumberOfUnitInCartoon(5);
        product_2.setPriceOfCartoon(825);
        product_2.setUrlOfImage("https://i.ibb.co/MRDwnqj/horseshoe.jpg");
        return new ArrayList<>(Arrays.asList(product_1, product_2));
    }
}
额外补充
  • 如果你不想用Mock,想让测试加载真实的ProductService实现,可以去掉@MockBean注解,同时在测试类上添加@Import(ProductServiceImpl.class)来引入真实服务类。不过@WebMvcTest的设计初衷是聚焦控制器层的单元测试,用Mock隔离服务层是更合理的单元测试做法。
  • 你的测试方法名getEmployees和产品业务不匹配,我顺手改成了getAllProducts,你可以根据实际情况调整。

内容的提问来源于stack exchange,提问作者Nafaz M N M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:52:32