如何为Moq显示内部接口?

Val*_*nko 38 c# nunit unit-testing moq internal

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

  • 签名
  • 结构
  • 测试

签名具有公共和内部接口.它也有

  [assembly: InternalsVisibleTo("Structures")]
  [assembly: InternalsVisibleTo("Tests")]
Run Code Online (Sandbox Code Playgroud)

在AssemblyInfo.cs中.

结构有公共和内部类和

  [assembly: InternalsVisibleTo("Tests")]
Run Code Online (Sandbox Code Playgroud)

在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>
Run Code Online (Sandbox Code Playgroud)

在packages.config中作为NuGet包.

我从Signatures和Structures的内部类中为内部接口编写了一些单元测试.运行,并有下一个结果:异常:

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

似乎合乎逻辑.我将[assembly:InternalsVisibleTo("InternalsVisible.DynamicProxyGenAssembly2")]添加到了Signatures and Structures项目的装配信息中.运行,并有下一个结果:异常:

从程序集"DynamicProxyGenAssembly2,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null"中键入"Castle.Proxies.IReminiscenceableDataTableProxy"正在尝试实现无法访问的接口.

这是有帮助的,但没有.仅更改异常消息.

如何解决我的问题?

k.m*_*k.m 72

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

[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]
Run Code Online (Sandbox Code Playgroud)

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

[assembly: InternalsVisibleTo("InternalsVisible.DynamicProxyGenAssembly2")] 
Run Code Online (Sandbox Code Playgroud)

将其更改为:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 
Run Code Online (Sandbox Code Playgroud)

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

从装配型"Castle.Proxies.IReminiscenceableDataTableProxy' DynamicProxyGenAssembly2(...)

  • 似乎Castle Project公开了一个`const`成员,就像消息一样,参见[`Castle.Core/Core/Internal/InternalsVisible.cs`](https://github.com/castleproject/Core/blob/master /src/Castle.Core/Core/Internal/InternalsVisible.cs),但看起来由于Castle Project嵌入在`Moq.dll`中的方式,当通过Moq看到这个类时,这个类变得非公开,因为它无法访问,说`[assembly:InternalsVisibleTo(Castle.Core.Internal.InternalsVisible.ToDynamicProxyGenAssembly2)]`将不起作用.所以你必须拥有自己的魔法弦. (5认同)

Mar*_*tin 14

在 .Net Core / .NET 5 中,您还可以将用户 DanKodi 的回答与本文结合起来这样您就不需要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 an other test code is able to instanciate objects of 'internal' classes -->
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
        <_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
    </AssemblyAttribute>

</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
这会执行以下操作:

  • 它使程序集对包含测试的项目可见(只要测试项目的名称是要测试的带有“.Tests”后缀的项目的名称)
  • 它使Moq(和其他测试代码)能够实例化该测试项目的内部类


Red*_*ood 10

在.NET 5中,可以将以下内容添加到.csproj中

<ItemGroup>
  <InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

来源: https: //github.com/dotnet/sdk/pull/3439

来源:https ://stackoverflow.com/a/66055829/4503491


Dan*_*odi 8

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

<ItemGroup>
    <!-- For Moq to mock internal class objects -->
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
      <_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
    </AssemblyAttribute>
  </ItemGroup>
Run Code Online (Sandbox Code Playgroud)