c#“internal"在进行单元测试时访问修饰符

我是单元测试的新手,我试图弄清楚我是否应该开始使用更多的internal访问修饰符。我知道如果我们使用internal并设置程序集变量InternalsVisibleTo,我们可以测试不想在测试项目中声明为公共的函数。这让我觉得我应该总是使用internal,因为至少每个项目(应该?)都有自己的测试项目。你们能告诉我为什么我不该这么做吗?什么时候我应该使用private?

195541 次浏览

你也可以使用private,你可以调用带有反射的private方法。如果你使用Visual Studio Team Suite,它有一些很好的功能,会生成一个代理来调用你的私有方法。下面是一篇代码项目文章,演示了如何自己对私有方法和受保护方法进行单元测试:

http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx

至于应该使用哪个访问修饰符,我的一般经验法则是先使用private,然后根据需要逐步升级。通过这种方式,您将尽可能少地暴露类的内部细节,这有助于保持实现细节的隐藏,就像它们应该隐藏的那样。

如果您想测试私有方法,请查看Microsoft.VisualStudio.TestTools.UnitTesting命名空间中的PrivateObjectPrivateType。它们为必要的反射代码提供了易于使用的包装器。

< p >文档: # EYZ0, # EYZ1 < / p >

VS2017 &2019年,你可以通过下载MSTest找到这些。TestFramework nuget

默认使用private。如果一个成员不应该在该类型之外公开,那么它也不应该在该类型之外公开,即使是在同一个项目中。这使事情更安全、更整洁——当你使用对象时,你可以更清楚地使用哪些方法。

话虽如此,我认为有时出于测试目的将自然私有方法设置为内部方法是合理的。比起反射,我更喜欢这种方法,因为反射对重构不友好。

需要考虑的一件事可能是“ForTest”后缀:

internal void DoThisForTest(string name)
{
DoThis(name);
}


private void DoThis(string name)
{
// Real implementation
}

然后,当您在同一个项目中使用该类时,很明显(现在和将来)您不应该真正使用这个方法——它只是用于测试目的。这有点俗气,我自己也不这么做,但至少值得考虑。

内部类需要测试,并且有一个程序集属性:

using System.Runtime.CompilerServices;


[assembly:InternalsVisibleTo("MyTests")]

将此添加到项目信息文件中,例如Properties\AssemblyInfo.cs,用于测试中的项目。在这种情况下" mytest "是测试项目。

除了Eric的回答,你还可以在csproj文件中配置:

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>MyTests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

或者如果你每个项目都有一个测试项目要测试,你可以在Directory.Build.props文件中这样做:

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Test</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
< p >看到:# EYZ0 < br > 例如:# EYZ0 < / p >

我使用.NET Core 3.1.101.csproj添加,为我工作是:

<PropertyGroup>
<!-- Explicitly generate Assembly Info -->
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>


<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>MyProject.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

在。net Core 2.2中,将这一行添加到Program.cs中:

using ...
using System.Runtime.CompilerServices;


[assembly: InternalsVisibleTo("MyAssembly.Unit.Tests")]


namespace
{
...

InternalsVisibleTo.cs文件添加到项目的根文件夹,其中.csproj文件存在。

InternalsVisibleTo.cs的内容应该如下

using System.Runtime.CompilerServices;


[assembly: InternalsVisibleTo("AssemblyName.WhichNeedAccess.Example.UnitTests")]
对于.NET core,您可以将属性添加到命名空间为 [组装:InternalsVisibleTo(“MyUnitTestsAssemblyName")]。 例如:

using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Applications.ExampleApp.Tests")]
namespace Applications.ExampleApp
internal sealed class ASampleClass : IDisposable
{
private const string ApiVersionPath = @"api/v1/";
......
......
......
}
}

从。net 5开始,你也可以在被测试项目的csproj中使用这个语法:

  <ItemGroup>
<InternalsVisibleTo Include="MyProject.Tests" />
</ItemGroup>