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

单元测试中如何mock私有方法返回值以完成findById方法测试

问题说明

现有服务类方法如下:

public List<ProductDTO> findById(final int id) {
    final List<String> categoryList = getCategoryById(id);
    final List<UUID> productUuidList = 
        productRepository.findAllUuidByCategoryIdIn(categoryList);
    return getProductDTOList();
}

private static List<String> getCategoryById(final int id) {
    // 省略内部实现
    return ...
}

单元测试代码如下:

@Test
public void test_findByZoneOffset() {
    List<String> categoryList = new ArrayList<>();
    // 省略构造categoryList的逻辑
    final List<UUID> productUuidList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        productUuidList.add(UUID.randomUUID());
    }
    when(productRepository.findAllUuidByCategoryIdIn(categoryList))
        .thenReturn(productUuidList);
    // 省略其他逻辑
    final List<ProductDTO> productDTOList = productService.findById(5);
}

遇到的问题:无法构造出和私有方法getCategoryById返回值完全一致的categoryList,该私有方法内部没有调用其他外部依赖,不希望在单元测试中直接调用该私有方法,想要mock一个categoryList让findById运行时获取到的就是mock的内容,该如何实现?

实现方案

可以通过PowerMock框架mock私有静态方法的返回值实现需求,操作步骤如下:

  • 首先引入PowerMock和Mockito的整合依赖,匹配你项目的JDK、Spring版本即可。
  • 给测试类添加如下注解:
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(你的服务类.class) // 替换为你实际的服务类类名
    
  • 修改测试用例,对私有静态方法打桩,示例代码如下:
    @Test
    public void test_findByZoneOffset() {
        // 自定义你需要的mock返回值
        List<String> mockCategoryList = Arrays.asList("分类1", "分类2", "分类3");
        // 对服务类的静态方法进行spy
        PowerMockito.spy(你的服务类.class);
        // 当私有静态方法getCategoryById入参为5时,返回我们构造的mockCategoryList
        PowerMockito.doReturn(mockCategoryList)
            .when(你的服务类.class, "getCategoryById", 5);
    
        // 原有repository打桩逻辑直接用mockCategoryList即可
        final List<UUID> productUuidList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            productUuidList.add(UUID.randomUUID());
        }
        when(productRepository.findAllUuidByCategoryIdIn(mockCategoryList))
            .thenReturn(productUuidList);
    
        // 调用测试方法
        final List<ProductDTO> productDTOList = productService.findById(5);
        // 后续添加你的断言逻辑即可
    }
    

如果不想引入PowerMock这类修改字节码的测试框架,更规范的改造方式是将getCategoryById方法抽为独立工具类的公共方法,之后直接mock该工具类的方法返回值即可,更符合可测性设计要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 12:27:03