我试图弄清楚我是否应该开始使用更多的内部访问修饰符。

我知道如果我们使用internal并设置程序集变量InternalsVisibleTo,我们可以测试不想在测试项目中声明为公共的函数。

这让我觉得我应该总是使用internal,因为至少每个项目(应该?)都有自己的测试项目。

为什么不应该这样做呢?什么时候应该使用private?


当前回答

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

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

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

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

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

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

其他回答

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

文档: PrivateType, PrivateObject

对于VS2017和2019,你可以通过下载MSTest找到这些。TestFramework nuget

我使用的是。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,您可以将属性添加到命名空间 [组装: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/";
        ......
        ......
        ......
        }
    }

将InternalsVisibleTo.cs文件添加到项目根文件夹中。csproj文件。

InternalsVisibleTo.cs的内容应该如下

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("AssemblyName.WhichNeedAccess.Example.UnitTests")]

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

using System.Runtime.CompilerServices;

[assembly:InternalsVisibleTo("MyTests")]

将此添加到项目信息文件中,例如Properties\AssemblyInfo.cs,用于测试中的项目。在本例中,“MyTests”是测试项目。