在 VS2017.NET 标准库中对内部方法进行单元测试

我目前正在创建一个 VisualStudio2017候选发行版,以便使用最新的 VisualStudio2017发行版。NET 标准1.6库。我正在使用 xUnit 对我的代码进行单元测试,我想知道您是否仍然可以测试 VS2017中的内部方法。

我记得您可以在 VS2015中的 AssemblyInfo.cs 类中添加一行,使指定的项目能够查看内部方法:

[assembly:InternalsVisibleTo("MyTests")]

因为在 VS2017中没有 AssemblyInfo.cs 类。NET 标准的项目,我想知道,如果你仍然可以单元测试内部方法?

47762 次浏览

根据 InternalsVisibleToAttribute的.NET 文档:

该属性应用于程序集级别。这意味着它可以包含在源代码文件的开头,也可以包含在 VisualStudio 项目中的 AssemblyInfo 文件中。

换句话说,您可以简单地将它放在您自己的任意命名的.cs 文件中,它应该可以正常工作:

// some .cs file included in your project
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]

“ InternalsVisibleTo”属性是任何类型的“ white-box”(我猜是十年的术语)测试的关键。网。它可以放在任何 c # 文件中,前面带有“ Assembly”属性。请注意,MSDOCs 说,如果程序集名称已经签名,那么它必须由公钥令牌限定。有时候这不起作用,必须使用完整的公钥。对内部构件的访问是测试并发系统和许多其他情况的关键。参见 https://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054。在这本书中,Meszaros 描述了各种编码风格,它们基本上构成了程序开发的“为测试而设计”的方法。至少这些年我一直是这么用的。

补充说明: 抱歉,我有段时间没来了。一种方法被 Meszaros 称为“测试子类”方法。同样,必须使用“ interalsvisableto”来访问基类的内部结构。这是一个很好的解决方案,但是它不适用于密封类。当我教授“为测试而设计”的时候,我建议这是为了提供可测试性而需要“预先设计”到基类中的事情之一。这必须成为一种文化现象。设计一个未密封的“基”基类。称之为 UnsealedBaseClass 或者其他可以一致识别的名称。这是要为测试子类化的类。它还被子类化以构建生产密封类,该类通常只在其公开的构造函数中有所不同。我的工作在核工业和测试的要求是非常认真的。所以,我不得不一直想着这些事情。顺便说一下,在产品代码中保留测试挂钩在我们的领域中不被认为是一个问题,只要它们在。净执行额。不测试某些东西的后果可能是相当深远的。

第一个答案完全没问题。如果您觉得您仍然想在原来的 AssemblyInfo中这样做,您总是可以选择不自动生成文件并手动添加它。

<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

了解更多信息: Https://stackoverflow.com/a/47075759/869033

另一种方法是在目标项目中使用一个“包装器”TestMyFoo 公共类,该类具有公共方法,并从您需要测试的类继承(例如 MyFoo)。这些公共方法只是调用要测试的基类。

这不是“理想的”,因为您最终会在您的目标项目中提供一个测试挂钩。但考虑现代可靠的汽车船舶与诊断港口和现代可靠的电子船舶与 JTAG 连接。但是没有人会傻到使用诊断端口来驾驶他们的汽车。

如下所述:

Https://blog.sanderaernouts.com/make-internals-visible-with-new-csproj-format

可以通过添加另一个 ItemGroup 在项目文件中添加内部可见属性:

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(AssemblyName).Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

甚至:

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

我喜欢这个解决方案,因为项目文件似乎是定义这些问题的正确位置。