BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

单元测试 vs. 私有方法

| 作者 李剑 关注 1 他的粉丝 发布于 2009年2月5日. 估计阅读时间: 2 分钟 | CNUTCon 了解国内外一线大厂50+智能运维最新实践案例。

前几天,Naresh Jain在Managed Chaos上发了篇博客,总结了一些测试中的bad smell。例如:

一个方法中有太多test case——被测试的方法做了太多事情。
太多的setup/teardown——表示被测试类的耦合性太高。
改变一个地方,多处测试受影响——也许是测试的设计问题,也许是实现代码中有过多依赖。
测试上下文中有太多依赖——设计中的耦合性太高。
测试运行速度缓慢——表示你的单元测试也许在使用外部系统,例如网络、数据库、文件系统等等。通常也意味着被测试类有过多的职责。
……

里面还有一条:

为了测试的目的,把成员变量或者方法的访问权限变成protected或者public——可能是因为测试代码跟被测试的代码耦合太高,也可能是本来私有的东西有太多行为,这种情况下应该考虑把它抽出来作为独立的对象。

怎么为私有方法写单元测试?这个难题由来已久了。

有人会选择跳过私有方法,有人会选择去掉private限定符;跳过私有方法自然不是良策,但提升访问权限也会破坏封装,在Naresh Jain看来也算得上是bad smell,那怎么解决才好?

Naresh Jain对此语焉不详,不过还好,Agile Tips在08年11月有一篇文章介绍了怎么测试私有方法。文末作者说道:

应该为私有方法添加测试么?

我的答案是,在成功的用了TDD或者测试驱动重构(Test-Driven Refactoring)以后,你的代码中就不会出现针对私有方法的测试。

如果你用TDD编写全新的代码,在没有测试之前是没有功能的。私有方法是到了重构那一步的最后才会出现。把代码转移到私有方法中的这个过程,已经被先前写过的测试覆盖到了。所以,如果你成功了用了TDD,代码中就不会出现针对私有方法的测试。

如果你在改善遗留代码,你就该使用测试驱动重构。这样的话,可能会临时针对私有方法写一些测试。但是,随着测试覆盖率的增加,那些public方法的测试会覆盖到所有的路径,也包括了私有方法的调用。所以,你也不再需要测试私有方法。

在文中,作者也举了一些简单例子说明了用TDD的方式重构出私有方法,以及用测试驱动重构处理遗留代码的方式,更多细节请阅读原文

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

也就是说 by Wang Yuxing

也就是说私有方法是不能测试的

Re: 也就是说 by Gu Jun

为什么不能用反射来测试私有方法?

Re: 也就是说 by 曹 云飞

私有的东西有太多行为,这种情况下应该考虑把它抽出来作为独立的对象。

Re: 也就是说 by Jacky Li

为什么不能用反射来测试私有方法?

用反射……您怎么重构啊

Re: 也就是说 by 张 核铭

或许可以这样理解:单元测试的目标应该是被测对象的公开行为,是将被测对象作为黑盒的模拟环境。

所以,这恰恰是私有成员存在的理由。

Re: 也就是说 by 胡 键

私有方法需要测试么?!如果私有方法有问题,那么调用它的公有方法肯定会反映出来问题。而且,对于对象来说,私有方法属于它自己的管辖范围,测试重点还应该是它的职责,即公共方法。

Re: 也就是说 by blogbin avatar

同感!
重点测公共方法即可!

问题的本质 by Jin Ming

首先问个问题,私有方法来自何处?
1. 使用TDD重构而来的
文中已经讲到,代码中不会出现针对私有方法的测试
2. 改善遗留代码
改要测试的私有方法为包可见,添加相关测试,再进行重构。最终的重构结果也是代码中不会出现针对私有方法的测试

所以问题的本质在于私有方法是不是由需求驱动出来的,而且承担的职责足够简单。

测试的bad smell by Wong Peter

一个方法中有太多test case——被测试的方法做了太多事情。
太多的setup/teardown——表示被测试类的耦合性太高。
改变一个地方,多处测试受影响——也许是测试的设计问题,也许是实现代码中有过多依赖。
测试上下文中有太多依赖——设计中的耦合性太高。
测试运行速度缓慢——表示你的单元测试也许在使用外部系统,例如网络、数据库、文件系统等等。通常也意味着被测试类有过多的职责。

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

9 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT