[深入JUnit] 为什么别测试private函数
[深入JUnit] 为什么别测试private函数
摘自http://www.tuicool.com/articles/iumaayJ
比如说,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()
以及 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的私有函数。
}
}
在上面的代码里,由于 BirdTest 与 Bird 在一个package test.sample 里,所以 Bird 所有的 public 和 protected 函数,对 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 进行测试。
如果您有不同意见,欢迎与我讨论。
[深入JUnit] 为什么别测试private函数的更多相关文章
- Junit测试private方法
package com.bill99.junit; public class ACase { private String echoRequest(String request) { return & ...
- Spring-test使用JUnit时,测试类autowired报错,create bean error
Spring-test使用JUnit时,测试类里面使用autowired会报错, 报create bean error...... 但是controller里面@autowired可以正常运行的. 在 ...
- Android中使用自身携带的Junit新建一个测试工程
1.新建立一个Android工程 package com.shellway.junit; public class Service { public int divide(int a,int b){ ...
- 测试一个函数的运行时间(C++)
#include <ctime> static clock_t Start,Finish; Start=clock(); fun(); Finish = clock(); double t ...
- 如何在单元测试中测试异步函数,block回调这种
大概有四种方法: runloop 阻塞主进程等待结果 semphaore 阻塞主进程等待结果 使用XCTestExpectation 阻塞主线程等待(我用这个,xcode自带的,为啥不用) 使用第三方 ...
- Java高级特性 第11节 JUnit 3.x和JUnit 4.x测试框架
一.软件测试 1.软件测试的概念及分类 软件测试是使用人工或者自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别.它是帮助识别开发完成(中间或最终 ...
- Maven聚合、Maven仓库jar包以及Spring+MyBatis+JUnit+Maven整合测试的搭建过程
一.Maven将父项目创建到父项目的内部 在父项目的pom.xml上 点右键,选择maven-->new-->maven module project 二.Maven聚合 在某个项目的p ...
- .NET中如何测试Private和Protected方法
TDD是1)写测试2)写通过这些测试的代码,3)然后重构的实践.在,NET社区中, 这个概念逐渐变得非常流行,这归功于它所增加的质量保证.此时,它很容易测试public方法,但是一个普遍的问题出现了, ...
- 使用timeit测试Python函数的性能
timeit是Python标准库内置的小工具,可以快速测试小段代码的性能. 认识timeit timeit 函数: timeit.timeit(stmt, setup,timer, number) 参 ...
随机推荐
- 关闭myeclipse中jsp的校验功能
window--->preference--->Myeclipse--->Validation,取消下图红框中的选中状态.
- ios 数组倒序和数组转字符串
NSMutableArray *array = [NSMutableArray arrayWithObjects:",nil]; NSArray* reversedArray = [[arr ...
- INSERT command denied to user
问题分析: 网站运行突然出现下面的 MySQL 错误: 645297 [http-88-13] ERROR com.mes.cart.dao.impl.CartDAOImpl - CartDAOImp ...
- lesson7:java线程池
在jdk1.5的版本中,java提供了语言级别的线程池,对于需要使用线程池的业务系统和中间件框架等提供了方便的选择.我认为线程池主要有两个方面的作用:第一就是防止因为外部条件的变化,造成线程数的瞬间飙 ...
- ajax:html5上传文件,上传之前可以实现本地预览
本主题主要涉及两个新内容: 1.上传文件(主要使用了FormData) 2.本地预览(主要使用了FileReader) html5的FormData其实就是平时的Form表单,只是html5可以直接新 ...
- [Cocos2d-x v3.x]序列帧动画
简单介绍 Cocos2d-x中.动画的详细内容是依靠精灵显示出来的,为了显示动态图片,我们须要不停切换精灵显示的内容.通过把静态的精灵变为动画播放器从而实现动画效果. 动画由帧组成,每一帧都是一个 ...
- Comprehensive learning path – Data Science in Python深入学习路径-使用python数据中学习
http://blog.csdn.net/pipisorry/article/details/44245575 关于怎么学习python,并将python用于数据科学.数据分析.机器学习中的一篇非常好 ...
- boost::pool与内存池技术
建议看这个链接的内容:http://cpp.winxgui.com/cn:mempool-example-boost-pool Pool分配是一种分配内存方法,用于快速分配同样大小的内存块, ...
- (转)url重写
使用URLRewriter.dll后,根本不需要使用任何代码,我之前做的项目就是用的做URL重写的,其实不是进化,其实表面上看是.html扩展名而已,当然你还可以用其他的任意扩展名下面是你的配置 &l ...
- c - 每位数字尾部加空格
/* input:一个4位整数. output:每位整数后紧跟一个空格的字符串. */ char * insert(char *s) { int len = strlen(s); * len + ); ...