今天在InfoQ上闲逛,发现一群人在讨论该不该为私有方法写单元测试.当然了,没有什么新意.支持的一方说,单元测试就是要控制很小的测试颗粒度,而且私有方法可能会非常复杂,无法通过Public API进行全面的测试.反对的一方就说,私有方法不需要测试,因为对外界不可见,TDD只需要代码通过测试即可.私有方法太复杂就需要进行重构.
最终,我看到一条回复,颇有中庸的味道,基本上来说,不要针对私有方法写单元测试,如果需要写的话,先要说清楚,为什么要把这个方法设置成私有,而不是公有.最终例外的一些私有方法需要进行单元测试可以采用方法注入的方式,步骤摘抄如下
1) You create an inner class within the class under test - call it TestProbe
2) You create an accessor to that probe in the parent class - something like getTestProbe()
3) Because the inner class has access to all the private methods and variables, you can add as many getters/setters as you want to fudge with the inner state of the class under test.
4) You get to keep the parent class's original private variables and methods and minimally modify it's public interface by adding one getter: getTestProbe().
An example of a TestProbe might look something like this:
public class Foo {
private Map cache;
private int itemsInCacheMatching(String pattern) {
}
![](/Images/OutliningIndicators/InBlock.gif)
/** For tests only. NOT TO BE USED BY PRODUCTION CODE. */
public class TestProbe {
public Map cache() { return cache; }
public int itemsInCacheMatching(String pattern) {
return Foo.this.itemsInCacheMatching(pattern);
}
}
![](/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
}
最终,我看到一条回复,颇有中庸的味道,基本上来说,不要针对私有方法写单元测试,如果需要写的话,先要说清楚,为什么要把这个方法设置成私有,而不是公有.最终例外的一些私有方法需要进行单元测试可以采用方法注入的方式,步骤摘抄如下
1) You create an inner class within the class under test - call it TestProbe
2) You create an accessor to that probe in the parent class - something like getTestProbe()
3) Because the inner class has access to all the private methods and variables, you can add as many getters/setters as you want to fudge with the inner state of the class under test.
4) You get to keep the parent class's original private variables and methods and minimally modify it's public interface by adding one getter: getTestProbe().
An example of a TestProbe might look something like this:
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)