资讯专栏INFORMATION COLUMN

[深入JUnit] 为什么别测试private函数

happyhuangjinjin / 2685人阅读

摘要:比如说,是我们要测试的,它有以及的方法。对这个而言,它可见的所有函数,是的返回值。非法,不能调用的私有函数。与其实区别不大。或者,也许这个函数其实应该被声明称。那么,根据原则,这个函数就应该被放到一个多带带的里面。然后,对进行测试。

比如说,Bird是我们要测试的class,它有public, protected,以及private的方法。

// 文件位置:src/test/sample/Bird.java
package test.sample;
class Bird {
  public void fly() { ... }
  public void eat() { ... }
  protected void singRandomly() { 
    final Song s = findASong();
    singASong(s);
  }
  
  private Song findASong() { ... }
  private void singASong() { ... }
}

现在有一个BirdTest class。对这个class而言,它可见的所有函数,是Bird.class.getDeclaredMethods()的返回值。

代码细节请看
junit.internal.MethodSorter#getDeclaredMethods()
http://grepcode.com/file/repo1.maven.org/maven2/junit/junit/4.12/org/junit/internal/MethodSorter.java#MethodSorter.getDeclaredMethods%28java.lang.Class%29
以及java.lang.Class#getDeclaredMethods()
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/Class.java#Class.getDeclaredMethods%28%29

所有的public, protected, private方法BirdTest都能看到。但是,看到不等于能调用

// 文件位置:tst/test/sample/BirdTest.java
package test.sample;
class BirdTest {
  @Test
  public void testFly_CaseDescription1() {
    ...
    bird.fly(); //当然ok,因为Bird#fly是public的
  }

  @Test
  public void testSingRandomly_CaseDescription1() {
    ... 
    bird.sing(); //ok,因为BirdTest也在test.sample package下面。否则是非法的。
  }

  @Test
  public void testFindASong() {
    ...
    bird.findASong(); // 非法,不能调用Bird的私有函数。
  }
}

在上面的代码里,由于BirdTestBird在一个package test.sample里,所以Bird所有的publicprotected函数,对BirdTest可见。但是,private应该是不可调用的。

当然,有人会告诉你如何利用java reflection的API来让private method也可以调用

// 无关紧要的parameter用 "_" 略去了
Method findASong = targetClass.getDeclaredMethod("findASong", _);
findASong.setAccessible(true);
return findASong.invoke(_, _);

但是,这打破了Bird类的封装,是非常不好的。设想,改动private的方法的声明会造成test failure,那么private就失去意义了。与protected其实区别不大。

那么应该怎么做呢?

不去测试private函数,好的private函数都应该是很小很简单的,测试那调用了private函数的public和protected方法即可。

或者,也许这个private函数其实应该被声明称protected。

如果以上方法你都觉得不合适,而某一个private函数很复杂,很需要测试。那么,根据Single Responsibility原则,这个private函数就应该被放到一个多带带的class里面。

class BirdSongs {
  protected Song findASong(Integer id) { ... }
  protected void singASong(Song s) { ... }
}

然后,对BirdSongs#findASong进行测试。

如果您有不同意见,欢迎与我讨论。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65678.html

相关文章

  • [深入JUnit] 测试运行的入口

    摘要:剧透如果您看了深入的秘密,里面的是通过本文涉及到的,一个叫的类,与连接到一起的。是今天的主角比如说我们有一个类,如何调用来运行测试有一个的类,他的描述是所以,这个是运行测试的一个入口。接下来,打算转战倡导。 showImg(https://segmentfault.com/img/bVtSbH); 阅读前提 了解JUnit 对JUnit的内部实现有兴趣 不妨看看[深入JUnit] @...

    springDevBird 评论0 收藏0
  • [深入JUnit] 测试运行的入口

    摘要:剧透如果您看了深入的秘密,里面的是通过本文涉及到的,一个叫的类,与连接到一起的。是今天的主角比如说我们有一个类,如何调用来运行测试有一个的类,他的描述是所以,这个是运行测试的一个入口。接下来,打算转战倡导。 showImg(https://segmentfault.com/img/bVtSbH); 阅读前提 了解JUnit 对JUnit的内部实现有兴趣 不妨看看[深入JUnit] @...

    godlong_X 评论0 收藏0
  • 深入理解 lambda表达式 与 MethodReference(四)

    摘要:陈杨一测试数据准备二方法引用引入方法引用集合遍历集合遍历集合遍历集合遍历三什么是 package com.java.design.java8.MethodReference; import com.java.design.java8.entity.Student; import org.junit.Before; import org.junit.Test; import org....

    EasonTyler 评论0 收藏0
  • [深入JUnit] @Before, @After, @Test的秘密

    摘要:最近对和的内部实现比较感兴趣,将在接下来的一段时间,和大家一起深入代码细节。利用原生的和,可以轻松地得到测试类中函数的。下期内容又被谁调用了呢运行的入口在哪里请看深入测试运行的入口 最近对JUnit和Mockito的内部实现比较感兴趣,将在接下来的一段时间,和大家一起深入代码细节。 王侯将相,宁有种乎 (JUnit也没啥Magic吧) 阅读前提 听说过Java Annotation ...

    dongfangyiyu 评论0 收藏0
  • 一起来学SpringBoot | 第五篇:使用JdbcTemplate访问数据库

    摘要:值得注意的是,默认会自动配置,它将优先采用连接池,如果没有该依赖的情况则选取,如果前两者都不可用最后选取。 SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程 Spring Framework对数据...

    ssshooter 评论0 收藏0

发表评论

0条评论

happyhuangjinjin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<