17

[当然,问题不限于特定的“朋友”实现,尽管如果相关,请随时指出实现细节]

阅读未回答的问题,我偶然发现了这个InternalsVisibleTo属性:

指定通常仅在当前程序集中可见的类型对另一个程序集可见。

MSDN上的C# Programming Guide有一节Friend Assemblies描述了如何使用属性来允许对另一个程序集使用方法和类型。internal

我想知道使用它来创建一个“隐藏”接口来检测库以供单元测试程序集使用是否是一个好主意。它似乎在两个方向上都大大增加了耦合(在生产程序集中测试代码,在测试代码中对生产程序集的深入了解),但另一方面,它可能有助于创建细粒度的测试,而不会弄乱公共接口。

你在测试时使用友元声明是什么体验?是你的银弹,还是它开始了死亡行军?

4

5 回答 5

14

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

虽然使用[InternalsVisibleTo]确实增加了耦合,但我相信(轻微的)增加是非常值得的。

我的单元测试已经与被测代码紧密耦合——尽管我尝试编写测试来确保特定的结果,而不是特定的实现,通过访问普通消费者不可见的东西,我确实在某种程度上限制了实现。

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

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

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

获得正确的属性可能有点繁琐,因为它需要包含测试程序集的公钥。IDesign 有一个有用的Friend Assembly 工具,可以在剪贴板上创建属性,准备粘贴。受到推崇的。

于 2008-11-04T08:06:02.393 回答
13

这是我个人申请过的唯一用途InternalsVisibleTo——而且确实非常非常方便。

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

于 2008-11-04T07:41:32.570 回答
3

我认为使用InternalsVisibleToAttribute启用单元测试是完全合理的。我在“单元测试”中的“单元”是一个类,其中包括internal类,所以我想测试它们。 不过,我不想对private方法进行单元测试。

我不认为为测试创建一个特殊的私有接口是一个好主意。单元测试的价值之一是它使您有机会从该类的使用者的角度考虑该类的接口;提供后门会带走这种好处。

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

于 2008-11-06T21:06:22.350 回答
3

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

我在这项技术上取得了巨大的成功。如果没有别的,它可以通过让您在无法访问的情况下调用私有方法来帮助您实现神话般的 100% 代码覆盖率目标。

于 2008-11-06T21:14:32.303 回答
2

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

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

于 2010-09-21T19:26:16.127 回答