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

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

时间 2016-03-28 10:58:03 SegmentFault
主题 JUnit

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

  1. // 文件位置:src/test/sample/Bird.java
  2. package test.sample;
  3. class Bird {
  4. public void fly() { ... }
  5. public void eat() { ... }
  6. protected void singRandomly() {
  7. final Song s = findASong(<some_random_number>);
  8. singASong(s);
  9. }
  10. private Song findASong() { ... }
  11. private void singASong() { ... }
  12. }

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

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

  1. // 文件位置:tst/test/sample/BirdTest.java
  2. package test.sample;
  3. class BirdTest {
  4. @Test
  5. public void testFly_CaseDescription1() {
  6. ...
  7. bird.fly(); //当然ok,因为Bird#fly是public的
  8. }
  9. @Test
  10. public void testSingRandomly_CaseDescription1() {
  11. ...
  12. bird.sing(); //ok,因为BirdTest也在test.sample package下面。否则是非法的。
  13. }
  14. @Test
  15. public void testFindASong() {
  16. ...
  17. bird.findASong(); // 非法,不能调用Bird的私有函数。
  18. }
  19. }

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

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

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

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

那么应该怎么做呢?

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

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

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

  1. class BirdSongs {
  2. protected Song findASong(Integer id) { ... }
  3. protected void singASong(Song s) { ... }
  4. }

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

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

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

  1. Junit测试private方法

    package com.bill99.junit; public class ACase { private String echoRequest(String request) { return & ...

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

    Spring-test使用JUnit时,测试类里面使用autowired会报错, 报create bean error...... 但是controller里面@autowired可以正常运行的. 在 ...

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

    1.新建立一个Android工程 package com.shellway.junit; public class Service { public int divide(int a,int b){ ...

  4. 测试一个函数的运行时间(C++)

    #include <ctime> static clock_t Start,Finish; Start=clock(); fun(); Finish = clock(); double t ...

  5. 如何在单元测试中测试异步函数,block回调这种

    大概有四种方法: runloop 阻塞主进程等待结果 semphaore 阻塞主进程等待结果 使用XCTestExpectation 阻塞主线程等待(我用这个,xcode自带的,为啥不用) 使用第三方 ...

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

    一.软件测试 1.软件测试的概念及分类 软件测试是使用人工或者自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别.它是帮助识别开发完成(中间或最终 ...

  7. Maven聚合、Maven仓库jar包以及Spring+MyBatis+JUnit+Maven整合测试的搭建过程

    一.Maven将父项目创建到父项目的内部 在父项目的pom.xml上 点右键,选择maven-->new-->maven module  project 二.Maven聚合 在某个项目的p ...

  8. .NET中如何测试Private和Protected方法

    TDD是1)写测试2)写通过这些测试的代码,3)然后重构的实践.在,NET社区中, 这个概念逐渐变得非常流行,这归功于它所增加的质量保证.此时,它很容易测试public方法,但是一个普遍的问题出现了, ...

  9. 使用timeit测试Python函数的性能

    timeit是Python标准库内置的小工具,可以快速测试小段代码的性能. 认识timeit timeit 函数: timeit.timeit(stmt, setup,timer, number) 参 ...

随机推荐

  1. struts2.1.*中再实现了一个servlet的方法

    学习Struts2也有一段时间了,今天用Servlet写了一个验证码,然后搬到Struts2中,惊奇地发现Servlet无法访问,出现404错误!后来折腾了半天,终于找出原因了.这也算我学习中的一个重 ...

  2. UUID.randomUUID()方法介绍

    UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法.UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机 ...

  3. 为什么要使用Nginx?

    这里做了些基准测试表明nginx打败了其它的轻量级的web服务器和代理服务器,同样也赢了相对不是那么轻量级的产品. 有人说这些基准测试是不准确的,因为在这样那样的环境下,做的比较不一致.我倾向同意基准 ...

  4. Android TextView属性

    android:autoLink设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接.可选值(none/web/email/phone/map/all)android:a ...

  5. Ubuntu 14.04 下手动安装Firefox的Flash插件

    有时候我们不得不採用手动安装一些软件. Ubuntu 14.04 下手动安装Firefox的Flash插件有下面几步 1. 下载Flash插件 下载地址为http://get.adobe.com/cn ...

  6. Word01-从正文处开始插入页码

    一份正式的文档应该由以下几部分组成:封面.目录.摘要.正文…… 现在要求前三页不需要插入页码,从正文部分插入页码为第一页,原文档如下: 步骤: 第一步:将光标移动到摘要页的末尾,选择页面部局--> ...

  7. Word02-隐藏回车换行符

    Word文档中每次输入回车后,会显示一个换行标志符,影响页面显示效果. 如下图,换行符隐藏前后: 设置方法:(选项-->显示-->段落标记前面的√去掉即可)

  8. JavaScript获取和设置CheckBox状态

    注意: 针对单个复选框的情况! var obj = document.getElementById("s1"); var value = obj.checked; alert(va ...

  9. mybati之day02

    今天开始讲解mybatis的第二天内容  一,拼接sql 在mapper.xml中,会多次使用到同一条sql片段,这时为了简便书写,将其定义出来 <sql id="base_sql&q ...

  10. this关键字之一个有趣的用法

    this关键字 1.首先一个用处就是代表当前类的对象. 2.当我们对构造函数进行重载的时候代码如下: public class Class1 { public string Name { get; s ...