如何做最小起订量可见的内部接口?

How to do internal interfaces visible for Moq?

我的 C# 解决方案中有 3 个项目。

签名有public和内部接口。 此外,它还有

  [assembly: InternalsVisibleTo("Structures")]
  [assembly: InternalsVisibleTo("Tests")]

在AssemblyInfo.cs中。

结构有 public 和内部 class 和

  [assembly: InternalsVisibleTo("Tests")]

在AssemblyInfo.cs中。

测试有下一个来源:

<packages>
  <package id="Moq" version="4.2.1409.1722" targetFramework="net45" />
  <package id="NUnit" version="2.6.4" targetFramework="net45" />
  <package id="NUnitTestAdapter" version="1.2" targetFramework="net45" />
</packages>

作为 packages.config 中的 NuGet 包。

我为 Signatures 的内部接口和 Structures 的内部 class 编写了单元测试。 运行,并得到下一个结果:异常:

Type Signatures.InterfaceX 对 DynamicProxy 不可见。无法为不可访问的类型创建代理。使类型 public 或内部并使用 [assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)] 属性标记您的程序集。

似乎合乎逻辑。我加了

[assembly: InternalsVisibleTo("InternalsVisible.DynamicProxyGenAssembly2")] 

到签名和结构项目的组装信息。 运行,并得到下一个结果:异常:

来自程序集 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' 的类型 'Castle.Proxies.IReminiscenceableDataTableProxy' 正试图实现一个不可访问的接口。

我预计它会有所帮助,但没有。 它只更改了异常消息。

如何解决我的问题?

建议的修复消息使用 const/static 字段作为程序集名称:

[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]

您使用了与程序集名称不对应的字符串:

[assembly: InternalsVisibleTo("InternalsVisible.DynamicProxyGenAssembly2")] 

改为:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 

您可以在错误消息中看到实际的程序集名称(应该出现在 InternalsVisibleTo 中):

Type 'Castle.Proxies.IReminiscenceableDataTableProxy' from assembly 'DynamicProxyGenAssembly2 (...)

将以下内容添加到定义了 类 的项目的 csproj 文件中。

<ItemGroup>
    <!-- For Moq to mock internal class objects -->
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
      <_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
    </AssemblyAttribute>
  </ItemGroup>

在 .Net Core / .NET 5 中,您还可以将用户 DanKodi 的回答与 this 文章相结合,因此您无需在任何地方设置 assembly 属性。

只需像这样编辑包含您要测试的代码的生产代码 .proj 文件:

<ItemGroup>

    <!-- Make assembly visible to test assembly -->
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(AssemblyName).Tests</_Parameter1>
    </AssemblyAttribute>

    <!-- Make assembly usable for Moq, so Moq is able to instanciate objects of 'internal' classes -->
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
        <_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
    </AssemblyAttribute>

</ItemGroup>

这将执行以下操作:

  • 它使程序集对包含测试的项目可见(如 只要测试项目的名称是你想要的项目名称 使用“.Tests”后缀进行测试)
  • 它使 mock 能够实例化该项目的内部 类