将私有方法公开给单元测试它......好主意?

版主注意:这里已经有39个答案了(部分已被删除)。 在发布答案之前,请考虑是否可以在讨论中添加有意义的内容。 你很可能只是重复别人已经说过的话。


我偶尔会发现自己需要在公开课上制作私人方法,只为它编写一些单元测试。

通常这是因为该方法包含在类中的其他方法之间共享的逻辑,并且它自己测试逻辑更加整洁,或者另一个原因可能是因为我想测试同步线程中使用的逻辑,而不必担心线程问题。

其他人是否发现他们自己这样做,因为我不喜欢这样做? 我个人认为,奖金超过了公开方法的问题,而这些方法并没有真正提供课堂以外的任何服务......

UPDATE

感谢大家的回答,似乎激起了人们的兴趣。 我认为普遍的共识是测试应该通过公共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());
    }
}

就个人而言,我宁愿使用公共API进行单元测试,我绝对不会公开私有方法,只是为了便于测试。

如果你真的想单独测试私有方法,在Java中你可以使用Easymock / Powermock来让你做到这一点。

你必须务实,你也应该知道事情难以测试的原因。

'听试验' - 如果难以测试,是否告诉了你关于你的设计的一些事情? 你可以重构一下这个方法的测试是否微不足道,并且可以通过公开的api测试来轻松覆盖?

Michael Feathers在“有效使用遗留代码工作”中要说的是:

“许多人花费大量时间试图找出如何解决这个问题......真正的答案是,如果你有试图测试私有方法的冲动,该方法不应该是私有的;如果公开方法让你感到困扰,很可能,因为它是单独责任的一部分,它应该放在另一个班上。“ [Feathers遗产代码有效地工作(2005)]


正如其他人所说,有人怀疑是单位测试私人方法; 单元测试公共接口,而不是私有实现细节。

也就是说,当我想单元测试C#中私有的东西时,我使用的技术是将可访问性保护从私有降级到内部,然后使用InternalsVisibleTo将单元测试程序集标记为朋友程序集。 单元测试程序集将被允许将内部结构视为公共对象,但您不必担心意外添加到公共表面区域。

链接地址: http://www.djcxy.com/p/39649.html

上一篇: Making a private method public to unit test it...good idea?

下一篇: What is the difference between integration and unit tests?