进行单元测试时的 C#“内部”访问修饰符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/358196/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:24:18  来源:igfitidea点击:

C# "internal" access modifier when doing unit testing

c#.netunit-testingtdd

提问by Hertanto Lie

I'm new in unit testing and I'm trying to figure out if I should start using more of 'internal' access modifier. I know that if we use 'internal' and set the assembly variable 'InternalsVisibleTo', we can test functions that we don't want to declare public from the testing project. This makes me think that I should just always use 'internal' because at least each project (should?) has it's own testing project. Can you guys tell me a reason why I shouldn't do this? When should I use 'private'?

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

采纳答案by EricSchaefer

Internal classes need to be tested and there is an assemby attribute:

需要测试内部类,并且有一个组件属性:

using System.Runtime.CompilerServices;

[assembly:InternalsVisibleTo("MyTests")]

Add this to the project info file, e.g. Properties\AssemblyInfo.cs.

将此添加到项目信息文件中,例如Properties\AssemblyInfo.cs.

回答by Steven Behnke

You can use private as well and you can call private methods with reflection. If you're using Visual Studio Team Suite it has some nice functionality that will generate a proxy to call your private methods for you. Here's a code project article that demonstrates how you can do the work yourself to unit test private and protected methods:

您也可以使用私有,并且可以通过反射调用私有方法。如果您使用的是 Visual Studio Team Suite,它有一些不错的功能,可以生成代理来为您调用私有方法。这是一篇代码项目文章,演示了如何自己完成对私有和受保护方法进行单元测试的工作:

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

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

In terms of which access modifier you should use, my general rule of thumb is start with private and escalate as needed. That way you will expose as little of the internal details of your class as are truly needed and it helps keep the implementation details hidden, as they should be.

就您应该使用的访问修饰符而言,我的一般经验法则是从 private 开始,并根据需要升级。这样,您将尽可能少地公开真正需要的类的内部细节,并且有助于保持实现细节的隐藏,因为它们应该是。

回答by Brian Rasmussen

If you want to test private methods, have a look at PrivateObjectand PrivateTypein the Microsoft.VisualStudio.TestTools.UnitTestingnamespace. They offer easy to use wrappers around the necessary reflection code.

如果你想测试私有方法,看一看PrivateObject,并PrivateTypeMicrosoft.VisualStudio.TestTools.UnitTesting命名空间。它们围绕必要的反射代码提供易于使用的包装器。

Docs: PrivateType, PrivateObject

文档: PrivateTypePrivateObject

For VS2017 & 2019, you can find these by downloading the MSTest.TestFramework nuget

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

回答by Jon Skeet

Keep using private by default. If a member shouldn't be exposed beyond that type, it shouldn't be exposed beyond that type, even to within the same project. This keeps things safer and tidier - when you're using the object, it's clearer which methods you're meant to be able to use.

默认情况下继续使用私有。如果成员不应超出该类型公开,则不应超出该类型公开,即使在同一项目中也是如此。这让事情更安全、更整洁——当你使用对象时,你应该能够使用哪些方法会更清楚。

Having said that, I think it's reasonable to make naturally-private methods internal for test purposes sometimes. I prefer that to using reflection, which is refactoring-unfriendly.

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

One thing to consider might be a "ForTest" suffix:

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

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

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

Then when you're using the class within the same project, it's obvious (now and in the future) that you shouldn't really be using this method - it's only there for test purposes. This is a bit hacky, and not something I do myself, but it's at least worth consideration.

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

回答by gldraphael

Adding to Eric's answer, you can also configure this in the csprojfile:

添加到 Eric 的答案中,您还可以在csproj文件中进行配置:

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

Or if you have one test project per project to be tested, you could do something like this in your Directory.Build.propsfile:

或者,如果每个要测试的项目都有一个测试项目,则可以在Directory.Build.props文件中执行以下操作:

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

See: https://stackoverflow.com/a/49978185/1678053
Example: https://github.com/gldraphael/evlog/blob/master/Directory.Build.props#L5-L12

请参阅:https: //stackoverflow.com/a/49978185/1678053
示例:https: //github.com/gldraphael/evlog/blob/master/Directory.Build.props#L5-L12

回答by Floating Sunfish

I'm using Dotnet 3.1.101and the .csprojadditions that worked for me were:

我正在使用Dotnet 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>

Hope this helps somebody out there!

希望这可以帮助那里的人!