【问题标题】:Is it considered bad practice to use InternalsVisibleTo for Unit Test Code?将 InternalsVisibleTo 用于单元测试代码是否被认为是不好的做法?
【发布时间】:2021-12-24 14:46:08
【问题描述】:

框架AssemblyInfo.cs中的示例代码:

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo
                          ("Test.Company.Department.Core")]

这是一种不好的做法吗?

【问题讨论】:

    标签: c# .net unit-testing


    【解决方案1】:

    不,这不被认为是不好的做法。如果出于充分的理由,您要测试的类在您的程序集中是内部的,则没有其他方法。只是不测试它们会更糟。

    【讨论】:

    • 如果你的类只是内部的,那么就没有办法使用它们。您可能会公开一个使用内部类的公共 API。然后应该可以通过公共 API 测试内部类(但是它可能或多或少困难)。最好通过公共 API 进行测试,因为它可以更轻松地重构内部 API。
    • @Rickard:我强烈反对:公共 API 旨在让其他人轻松使用。通过公共 API 测试内部类型的所有功能至少很麻烦。在每一个不那么小的 API 接口背后可能是一个具有复杂交互和分支的对象的完整图。测试公共 API 更像是集成测试。
    • 所以你觉得也可以测试私有成员和方法吗?
    • 没有。区别在于大小。您无法将私有方法与内部类甚至完整的对象图进行比较。
    • 我同意这一点。我说这没问题的理由是简单的实用主义:如果您在仅使用公共 API 时无法通过合理的努力编写合理的集中测试,请使用InternalsVisibleTo。否则,请使用公共 API。
    【解决方案2】:

    个人觉得还可以。我从来没有接受过“只测试公共方法”的教条。我认为有黑盒测试很好,但是白盒测试可以让你用更简单的测试来测试更多的场景,特别是如果你的 API 相当“笨重”并且公共方法实际上做了很多工作。

    同样,在一个封装良好的项目中,您很可能有多个内部类型只有个内部方法。现在大概这些会产生公共影响,因此您可以仅通过公共类型进行所有测试 - 但是您可能需要经过很多圈子才能真正测试真正的东西 使用InternalsVisibleTo 进行简单测试。

    【讨论】:

      【解决方案3】:

      InternalsVisibleTo 如果您需要测试您不想公开的 API 的子部分,这可能会很有用。

      但是,最好通过公共 API 进行测试,因为这样可以更轻松地重构内部 API。请谨慎使用InternalsVisibleTo,仅在适当时使用,例如API 的大小非常重要。

      【讨论】:

      • "...它使重构内部 API 变得更容易":需要考虑的具体点,谢谢。
      【解决方案4】:

      我认为这样做是完全合理的。

      我发现它对依赖注入非常有用。如果我有一个带有构造函数的类,它接受一些依赖项以允许对其进行单元测试,我经常将其标记为内部并在我的单元测试项目中公开它。然后我会有一个公共(无参数,或者至少参数少得多)构造函数。这使公共接口保持干净,并且仍然允许可测试的代码。

      【讨论】:

      • 让测试代码使用与生产代码不同的构造函数听起来是个坏主意
      【解决方案5】:

      不,如果使用得当,因为在某些情况下它是必要的。例如,您有单元测试A,它需要测试程序集B 的公共成员,该成员使用也在程序集B 中定义的一些内部类型。单元测试需要这种类型,所以必须使用InternalsVisibleTo

      它对于保护代码也很有用。 A 例如是一个激活程序集。您可能只希望解决方案中的一个模块访问您的激活程序集,并防止任何人添加对它的引用和调用方法。您可以将类型和成员设为内部,仅将它们公开给带有公钥令牌的签名程序集,并将其对世界其他地方隐藏。

      【讨论】:

        【解决方案6】:

        我会说这是不好的做法,因为如果您使用了 SOLID 原则,那么您真的不应该使用“InternalsVisibleTo”。但是我知道在“现实世界”中你会得到各种各样的代码.....所以务实的方法是最好的。

        此外,“InternalsVisibleTo”在您使用混淆的情况下并不理想。混淆器倾向于混淆“内部”的东西。因此,任何试图引用混淆 dll 内部的外部 dll 都会失败。您显然可以将混淆器配置为忽略外部引用的项目,但这会降低任何混淆器的有效性。

        我认为,如果可以,请避免使用“InternalsVisibleTo”。但是如果你必须使用它,那么代码的结构就会出现问题(你往往会得到很多)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-11
          • 1970-01-01
          • 2012-09-07
          • 2012-01-05
          • 1970-01-01
          • 2015-10-29
          相关资源
          最近更新 更多