如何在类库中测试一个内部类?

75
我想写一个类库,它可以为我创建一个复杂的对象,但是应该尽可能少地暴露给外部。我希望将其包含在其他项目中,然后只需调用这个类库一次,例如返回一个内部创建的对象。我不想让其他人显式地创建这些对象,但是我仍然想为这个类库创建一个测试项目。
例如:
var result = Manager.Instance.Create(definition)

这应该是访问类库的唯一途径。

根据定义参数,它使用不同的子类来创建所请求的实例,并相应地设置其属性。因此,我希望通过测试确保整个创建过程能够正常工作。但由于我也不想暴露结果对象的非常少的内部属性,因此我不能仅使用这个公共访问方法进行测试,因为我没有任何属性可以进行断言。

我知道你不应该测试内部机制,这通常是不好的设计,我也阅读了this article,但是难道没有任何方法可以创建一个包含单元测试项目的库,然后在之后限制对这个类的访问吗?用一个包装器或其他方式?


你在使用哪种编程语言? - Wouter de Kort
请勿重复:https://dev59.com/8nRC5IYBdhLWcg3wROpQ - CAD bloke
3个回答

163
在.NET中,你可以使用InternalsVisibleToAttribute在你的类库中使内部类型对你的单元测试项目可见。这样,你就可以使你的类保持内部状态,并且仍然可以从其他已授权的程序集中使用它。使用方法如下:
[assembly:InternalsVisibleTo("NameOfYourUnitTestProject")]

15
好的解决方案!以下是一些额外信息: 1)如果[assembly: ...]语法不熟悉:这些是程序集属性(http://msdn.microsoft.com/en-us/library/4w8c1y2s.aspx),其中最知名的是`AssemblyVersionAttribute`及其相关属性。 2)您可以在项目中的任何 .cs 文件中使用它们,位于命名空间之外,但通常在“属性”项目文件夹中指定 AssemblyInfo 文件中。 3)确实必须指定您的项目的 名称,而不是 命名空间,以防它们不同。 - Vincent Sels
太棒了,我不知道可以这样做,每天都能学到新东西! - MaYaN
1
谢谢。测试项目的名称是我缺少的。我找到了很多例子,但没有解释应该放入汇编命令的字符串。输入我的测试项目的名称就解决了问题! - Zeliax
我在想,如果有人创建了一个名为NameOfYourUnitTestProject的项目,它是否可以访问这些内部资源?我从安全角度考虑。 - Álvaro García

21

对于最新的csproj 2017格式的项目,如果您的项目没有AssemblyInfo.cs文件,您可以添加以下设置:

对于最新的 csproj 2017 格式的项目,如果你的项目没有 AssemblyInfo.cs 文件,你可以添加以下设置:

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

你还可以使用其他变量来代替MSBuildProjectName,例如AssemblyName或直接使用单元测试项目名称。

你可以在obj文件夹中的ProjectName.AssemblyInfo.csobj\Debug\netstandard2.0)中检查是否已通过添加InternalsVisibleTo进行了更新。


1
在我的情况下(.NET5应用程序),我需要csproj条目:
<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>MyAppName.UnitTests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

需要为我的类添加internalvisibleto属性才能使其正常工作:
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 
namespace MyAppName.Api.Something...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接