为了unit testing而改变方法可见性是否可行?

很多时候,我发现自己在一个私人的方法之间撕裂,以防止某人在没有意义的情况下调用它(或者搞砸了所涉及的对象的内部状态),或者使方法公开(或通常是内部的)以便将其暴露给unit testing组件。 我只是想知道Stack Overflow社区是怎么想到这个困境的?

所以我想这个问题真的是,关注可testing性还是保持适当的封装是更好的?

最近我一直倾向于可testing性,因为大多数代码只是由一小部分开发人员利用,但我想我会看到其他人都认为是什么?

这取决于方法是否是公共API的一部分。 如果某个方法不属于公共API的一部分,而是从同一个程序集中的其他types公开地调用,则使用internal,friend你的unit testing程序集,然后unit testing它。

但是,如果该方法不是/不应该是公共API的一部分,并且不被组件内部的其他types调用,则不要直接对其进行testing。 它应该是受保护的或私有的,只能通过对公共API进行unit testing来间接地进行testing。 如果您为您的types的非公共(或非公共)成员编写unit testing,则您将testing代码绑定到内部实现细节。

这是一种糟糕的耦合,增加了你需要的unit testing的数量,在短期内(更多的unit testing)以及长期(更多的testing维护和修改以响应重构的内部实现细节)增加了工作量。 testing非公共成员的另一个问题是您testing的代码可能并不实际需要或使用。 find死代码的一个好方法就是当你的公共API被覆盖100%时,没有被任何unit testing覆盖。 删除死代码是保持代码基础精益的一种好方法,如果您不小心将您的代码放到公共API中,以及代码的哪些部分是unit testing的,那么这是不可能的。

编辑:作为一个快速的附加说明…与正确devise的公共API,你可以非常有效地使用像微软的PEX工具来自动生成全覆盖的unit testing,testing您的代码的每个执行path。 结合一些涵盖关键行为的手动编写的testing,没有涉及的任何东西都可以被认为是无效代码,并且可以大大缩短您的unit testing过程。

在客户或用户可以看到的方法上更改方法可见性是不行的。 这样做是丑陋的,黑客,暴露的方法,任何愚蠢的用户可以尝试使用和爆炸你的应用程序…它的责任,你不需要。

你正在使用C#是吗? 查看内部可见的属性类。 你可以声明你的可testing方法是内部的,并允许你的unit testing程序集访问你的内部。

这是一个普遍的想法。

通常最好是通过testing调用它们的公共方法来testing私有方法(所以你没有明确地testing私有方法)。 但是,我知道有些时候你真的想要testing这些私有方法。

这个问题(Java)和这个问题(.NET)的答案应该是有帮助的。

为了回答这个问题:不,你不应该为了testing而改变方法的可见性。 你通常不应该testing私有方法,而当你这样做,有更好的方法来做到这一点。

一般来说,我同意@jrista。 但是,像往常一样,这取决于。

当试图使用遗留代码时,关键是要testing它。 之后,你可以添加testing新function和现有的错误,重构改善devise等,这是没有testing的风险。 遗留代码往往充斥着依赖关系,通常很难得到testing。

为了有效地处理遗留代码 ,Michael Feathers提出了多种获取testing代码的技术。 这些技术中的许多都涉及破坏封装或使devise复杂化,笔者就此前瞻。 一旦testing到位,代码可以被安全地改进。

所以对于遗留的代码,做你必须做的。

在.NET中,您应该使用访问器进行unit testing,而不是使用InternalsVisibleTo属性。 访问者允许你访问类中的任何方法,即使它是私有的。 他们甚至让你使用一个空的模拟派生对象来testing抽象类(参见“PrivateObject”类)。

基本上在你的testing项目中,你使用访问器类而不是实际的类来使用你想testing的方法。 访问器类与“真实”类相同,除了所有testing项目都公开。 Visual Studio可以为您生成访问器。

不要让一个types更容易看到,以方便unit testing。

国际海事组织(IMO)说不应该单独testing私人方法。 unit testing对于回归testing是非常有价值的,没有理由不能用粒度unit testing回归testing私有方法。