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

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

摘自http://www.tuicool.com/articles/iumaayJ

时间 2016-03-28 10:58:03 SegmentFault

原文  https://segmentfault.com/a/1190000004700616

主题 JUnit

比如说,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(<some_random_number>);
    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 进行测试。

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

时间: 2024-10-12 23:31:07

[深入JUnit] 为什么别测试private函数的相关文章

JUnit介绍及测试

一,JUnit介绍 终于到了白盒测试,话说黑盒测试实在是又没水准又无聊,白盒测试才能彰显我们技术人员的风采. 先上定义吧: JUnit是一个Java语言的单元测试框架.它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个. JUnit有它自己的JUnit扩展生态圈.多数Java的开发环境都已经集成了JUnit作为单元测试的工具.[1-3] JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框

spring && Cobertura && maven &&junit 单元测试以及测试覆盖率

1. 目的: junit 单元测试,Cobertura   测试覆盖率报告 项目目录结构 2. maven 配置 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://mave

JUnit之参数化测试和成组测试的使用

JUnit之参数化测试和成组测试的简单使用 参数化测试 正如数组替代int a0,a1,a2一样,测试加法时assertEquals(3.0, h.add(1, 2), 0.1);相当于声明一个变量,要测试100个怎么办. 所以,有了参数化测试,使用一个Collection收集所有的数据--加法时每一次测试需要的几个数据构成一组,n个组构成Collection. 然后按照JUnit的用法要求,写出单元测试类.(偷懒一下,不想写被测试的业务类X了.下面的例子中假设要测试的方法是,判断一个数是否奇数

ctype.h——使用测试字符函数

islower()                       是否为小写字母 isupper()                      是否为大写字母 isalpha()                       是否为字母 isalnum()                     是否为字母或十进制数字 iscntrl()                       是否为控制字符 isprint()                      是否为可打印字符(包含空格) isgra

Android中使用自身携带的Junit新建一个测试工程

1.新建立一个Android工程 package com.shellway.junit; public class Service { public int divide(int a,int b){ return a/b; } } Service.java.作为被测试类 package com.shellway.junit; import junit.framework.Assert; import android.test.AndroidTestCase; public class TestT

Spring-test使用JUnit时,测试类autowired报错,create bean error

Spring-test使用JUnit时,测试类里面使用autowired会报错, 报create bean error...... 但是controller里面@autowired可以正常运行的. 在网上提问,确认我一定是在扫描包上出现了问题.但是controller里面明明是可以得啊. 等等,我是使用maven构建的项目,项目分成了main.test两个部分.配置文件都在main文件夹下,那么扫到的包相应的都是mian文件夹下的包,而测试类所在的包扫描不到也就理所当然了. 解决方案:暂时先给t

Java高级特性 第11节 JUnit 3.x和JUnit 4.x测试框架

一.软件测试 1.软件测试的概念及分类 软件测试是使用人工或者自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别.它是帮助识别开发完成(中间或最终的版本)的计算机软件(整体或部分)的正确度 .完全度和质量的软件过程. 软件测试过程: 2.软件测试的分类 按是否关心软件内部结构和具体实现角度来分: 黑盒测试(Black-box Testing) 黑盒测试也称功能测试,测试中把被测的软件当成一个黑盒子,不关心盒子的内部结构是什么,只关心软件的输入

使用MockMVC与Junit进行单体测试

1.pom.xml追加 junit spring-test 2.测试共通类 @ContextConfiguration(locations = { "classpath:springframework/application-context.xml", "classpath:springframework/dispatcherservlet-servlet.xml" }) @RunWith(SpringJUnit4ClassRunner.class) @WebApp

junit 单元测试 - 参数化测试

junit4.x版本需要引入如下jar包: hamcrest-core-1.3.jar junit-4.12-beta-3.jar 新建一个计算器类,如下: package com.pt; public class Calculate { /** * 加法 * @param d1 * @param d2 * @return */ public static double add(double d1,double d2){ return d1 + d2; } /** * 减法 * @param d