主持人注:这里已经有39个答案了(有些已经删除了)。在你发表你的答案之前,考虑一下你是否可以为讨论添加一些有意义的东西。你很可能只是在重复别人已经说过的话。
我偶尔发现自己需要将类中的私有方法设为public,只是为了为它编写一些单元测试。
通常这是因为该方法包含类中其他方法之间共享的逻辑,并且单独测试逻辑更整洁,或者另一个原因可能是我想测试同步线程中使用的逻辑,而不必担心线程问题。
其他人发现他们这样做是因为我不喜欢吗?我个人认为,公开一个方法的好处超过了它在类之外没有提供任何服务的问题……
更新
谢谢大家的回答,似乎引起了大家的兴趣。我认为普遍的共识是测试应该通过公共API进行,因为这是使用类的唯一方式,我非常同意这一点。在我上面提到的几个案例中,我会这样做,这是不常见的情况,我认为这样做的好处是值得的。
然而,我可以看到,每个人都指出它不应该真的发生。再仔细想想,我觉得改变你的代码来适应测试是一个坏主意——毕竟我认为测试在某种程度上是一个支持工具,而改变一个系统来“支持一个支持工具”是明显的坏做法。
注意:
这个答案最初是针对以下问题发布的:单独的单元测试是否是通过getter公开私有实例变量的好理由?这是合并到这个,所以它可能是一个特定于这里提出的用例。
一般来说,我通常都支持重构“生产”代码,以使其更容易测试。然而,我不认为这是一个好的决定。一个好的单元测试(通常)不应该关心类的实现细节,只关心它的可见行为。与其将内部堆栈暴露给测试,不如测试类在调用first()或last()后是否按照预期的顺序返回页面。
例如,考虑以下伪代码:
public class NavigationTest {
private Navigation nav;
@Before
public void setUp() {
// Set up nav so the order is page1->page2->page3 and
// we've moved back to page2
nav = ...;
}
@Test
public void testFirst() {
nav.first();
assertEquals("page1", nav.getPage());
nav.next();
assertEquals("page2", nav.getPage());
nav.next();
assertEquals("page3", nav.getPage());
}
@Test
public void testLast() {
nav.last();
assertEquals("page3", nav.getPage());
nav.previous();
assertEquals("page2", nav.getPage());
nav.previous();
assertEquals("page1", nav.getPage());
}
}