VS2017 .Net标准库中的单元测试内部方法


150

我目前正在通过创建.Net Standard 1.6库来使用最新的Visual Studio 2017 Release Candidate。我正在使用xUnit对代码进行单元测试,并且想知道是否仍然可以在VS2017中测试内部方法。

我记得您可以在VS2015中全部使用AssemblyInfo.cs类,这将使指定的项目能够查看内部方法

[assembly:InternalsVisibleTo("MyTests")]

由于VS2017 .Net Standard项目中没有AssemblyInfo.cs类,我想知道您是否仍可以对内部方法进行单元测试?


3
应该能够仅通过外部可见的功能对代码进行单元测试。毕竟,如果没有来自外部代码的逻辑路径可以到达这些内部方法,那么它们首先将在那里做什么?
戴维(David)

3
@David我可以并且已经做到了,但是以前我已经在一些内部类周围进行了简单的单元测试。只是为了在测试中更加明确。
Phil Murray'17

5
AFAIK,您可以将此属性放置在namespace块外部的任何其他文件中,并且应该编译。不应有任何神奇的事物AssemblyInfo.cs。不行吗 当然,您需要添加正确的using子句或使用完全限定的attribute [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Something")]
Groo

1
@大卫如果要创建内部类库,你需要测试和模拟这些类,InternalsVisibleTo是至关重要的-在这里如- stackoverflow.com/a/17574183/43453
PandaWood

Answers:


209

根据.NET的文档InternalsVisibleToAttribute

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

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

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

1
@PhilMurray:也,似有是应该允许您创建一个“经典”的设置AssemblyInfo.cs文件一样解释在这里。否则,所有属性(如“描述”,“版权”和其他内容)都将存储在.csproj文件中。
Groo

43

如此处所述:

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>

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


8

虽然第一个答案是完全可以的。如果您仍然希望以原始AssemblyInfo格式执行此操作,则可以始终选择不自动生成文件并手动添加它。

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

有关更多信息:https : //stackoverflow.com/a/47075759/869033


5

“ InternalsVisibleTo”属性是对.Net进行任何形式的“白盒测试”(我猜是十年)的关键。可以将其放置在前面带有“ assembly”属性的任何c#文件中。请注意,MS DOC表示,如果程序集名称已签名,则必须使用公共密钥令牌进行限定。有时这不起作用,必须在其位置使用完整的公共密钥。内部访问是测试并发系统和许多其他情况的关键。参见https://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054。在本书中,Meszaros描述了各种编码样式,这些编码样式基本上构成了程序开发的“测试设计”方法。至少这就是我多年来使用它的方式。

添加:对不起,我已经有一段时间没有在这里了。一种方法被Meszaros称为“测试子类”方法。同样,必须使用“ internalsvisableto”来访问基类的内部。这是一个很棒的解决方案,但不适用于密封类。当我教“为测试而设计”时,我建议这是“预先设计”到基类中以提供可测试性的要求之一。它几乎已成为一种文化事物。设计一个未密封的“基”基类。将其称为UnsealedBaseClass或统一可识别的名称。这是要进行测试的子类。它也被子类化以构建生产密封类,该类通常仅在其公开的构造函数上有所不同。我在核工业工作,对测试要求非常重视。因此,我必须一直考虑这些事情。顺便说一句,将测试挂钩留在生产代码中在我们领域中不被认为是问题,只要它们在.Net实现中是“内部”即可。不测试某些东西的后果可能非常深远。


1

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

当您最终在目标项目中交付测试钩子时,这不是“理想的”方法。但考虑带诊断端口的现代可靠汽车和带JTAG连接的现代可靠电子产品。但是没有人愚蠢到可以使用诊断端口驾驶汽车。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.