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

Posted FserSuN

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 总结

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

以上是关于Java单元测试对私有方法测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Typescript 中对私有方法进行单元测试

java中的单元测试私有和静态方法

如何在Typescript中对私有方法进行单元测试

如何通过phpunit对一个方法进行单元测试,该方法具有多个内部调用保护/私有方法?

我应该对私有/受保护方法进行单元测试吗

如何对在 Swift 中调用的私有方法进行单元测试