使用“朋友” - 单元测试的声明。馊主意?

时间:2008-11-04 07:38:50

标签: .net unit-testing language-agnostic friend internalsvisibleto

[当然,问题不仅限于特定的“朋友”实现,请尽量指出相关的实施细节]

通过未解答的问题,我偶然发现了InternalsVisibleTo属性:

  

指定的类型   通常只在内部可见   当前组件可见   另一个集会。

C# Programming Guide上的MSDN有一个Friend Assemblies部分,介绍如何使用该属性允许将internal方法和类型用于其他程序集。

我想知道使用它来创建一个“隐藏”界面来检测库以供单元测试组件使用是否是一个好主意。它似乎在两个方向上大量增加耦合(测试生产程序集中的代码,关于测试代码中生产程序集的内部知识),但另一方面,它可能有助于创建细粒度的测试而不会使公共接口混乱。 / p>

您在测试时使用好友声明的经验是什么?它是你的银色子弹,还是它开始了死亡三月?

5 个答案:

答案 0 :(得分:13)

这是我曾亲自应用于InternalsVisibleTo的唯一用途 - 它确实非常非常方便。

我不认为单元测试是黑盒测试 - 它们已经在某种程度上与实现相结合。能够测试内部类型和方法可以实现更紧密的聚焦(更小的单位)。

答案 1 :(得分:13)

我已经广泛使用了这种技术 - 这意味着我的单元测试可以测试普通消费者看不到的代码库的各个方面。

虽然使用[InternalsVisibleTo]会增加耦合,但我相信(次要)增加非常值得获得。

我的单元测试已经与测试中的代码紧密耦合 - 虽然我尝试通过访问常规消费者看不到的东西来编写确保特定结果而非特定实现的测试,但我确实在某种程度上限制了实现。

另一方面,耦合是最小的 - 在代码程序集中具有[InternalsVisibleTo]属性,并将某些内容标记为内部而不是私有(或受保护的内部而不是受保护的)。

(请注意,我在这里忽略了使用单元测试引起的任何设计更改,这是一个完整的其他讨论。)

[InternalsVisibleTo]属性需要对程序集进行强命名。如果您还没有这样做,您可能会发现这有点麻烦,因为强名称程序集可能只依赖于其他强名称程序集,这可能最终导致您需要更改多个程序集。

正确获取属性可能有点繁琐,因为它需要包含测试程序集的公钥。 IDesign有一个有用的Friend Assembly tool,可以在剪贴板上创建属性,为粘贴做好准备。推荐使用。

答案 2 :(得分:3)

我认为使用InternalsVisibleToAttribute启用单元测试是完全合理的。 “单元测试”中的“单元”是一个类,包括internal个类,所以我想测试它们。 I don't want to unit test private methods,但是。

我不认为为测试创建一个特殊的私有界面是个好主意。单元测试的一个价值在于,它让您有机会从该类的消费者的角度考虑您的类的接口;提供后门可以带来好处。

然而,我的偏好是将我的单元测试与我的生产代码放在同一个程序集中。它通常不会影响我的客户,但它确实为我简化了事情,所以我这样做。当我这样做时,它会使InternalsVisibleTo问题消失。

答案 3 :(得分:3)

事实上,单元测试是唯一的使用,我已经能够使用InternalsVisibleToAttribute。有了这个,您可以将大部分“私有”方法实现为内部,而不是将它们暴露给单元测试框架,以便对类内部不变量进行更具侵略性的测试。

我用这种技术取得了很大的成功。如果没有别的东西可以让你在无法访问的情况下调用私有方法来帮助你实现神秘的100%代码覆盖率目标。

答案 4 :(得分:2)

我认为在将旧版C ++代码与更新的C#代码结合在一起时使用单独的程序集时会出现另一个合法用例。

我们已经使用了C ++程序集,将它们转换为C ++ / CLI,然后在C#中实现更新的代码。当我们这样做时,我们仍然会使用“内部”来表示C#中不真正公开的类/方法,然后将它们作为好友程序集提供给遗留代码。