Java单元测试对私有方法测试

1 概述

本文会首先简要说明为什么直接对私有方法测试不是一个好的实践。其次演示如果在必要的情况下如何测试私有方法

2 为什么不应该直接测试私有方法

我们写的单测应该只检查我们的公共方法。首先公有方法的调用者对公有方法内部使用的私有方法是无感知的。其次,好的设计对外接口应该是稳定的,在接口稳定的状态下,改变私有方法的实现不应该影响接口定义,因此也不应该影响我们的测试。

但有时也会遇到必须测试测试私有方法的情况,常见的场景如下:

  • 在私有方法中存在通过公有方法入口测试无法完成行覆盖的“死”代码。
  • 私有方法设计不合理,实现太复杂,根本没法通过测试完整覆盖,代码不可测。

因此,当我们觉得需要测试私有方法时,先考虑一下设计是否合理。

3 从私有方法中删除无法覆盖的代码

下面是一段需要测试的代码,公共方法validateAndDouble依赖doubleInteger。

private static Integer doubleInteger(Integer input) {
    if (input == null) {
        return null;
    }
    return 2 * input;
}

public static Integer validateAndDouble(Integer input) {
    if (input == null) {
        throw new IllegalArgumentException("input should not be null");
    }
    return doubleInteger(input);
}

我们写的单测如下

@Test
void givenNull_WhenValidateAndDouble_ThenThrows() {
    assertThrows(IllegalArgumentException.class, () -> validateAndDouble(null));
}

@Test
void givenANonNullInteger_WhenValidateAndDouble_ThenDoublesIt() {
    assertEquals(4, validateAndDouble(2));
}

接着通过JaCoCo插件检查覆盖率发现有段代码未覆盖到。
在这里插入图片描述
但仔细思考可以看到未覆盖代码实际并没有必要,因为外层已经做过检查,因此直接删除未覆盖代码即可。

4 对私有方法测试

假设不考虑合理性设计问题,那我们可以通过反射来对私有方法测试。

private Method getDoubleIntegerMethod() throws NoSuchMethodException {
    Method method = Utils.class.getDeclaredMethod("doubleInteger", Integer.class);
    method.setAccessible(true);
    return method;
}

@Test
void givenNull_WhenDoubleInteger_ThenNull() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
    assertEquals(null, getDoubleIntegerMethod().invoke(null, new Integer[] { null }));
}

@Test
void givenANonNullInteger_WhenDoubleInteger_ThenDoubleIt() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    assertEquals(74, getDoubleIntegerMethod().invoke(null, 37));
}

5 总结

本文简要讲了为什么测试私有方法不是一个好的实践,其次演示了如果一定要测试私有方法,如何通过反射的方式进行测试。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值