如何对 Moq 可见内部接口?
Posted
技术标签:
【中文标题】如何对 Moq 可见内部接口?【英文标题】:How to do internal interfaces visible for Moq? 【发布时间】:2015-03-29 20:08:10 【问题描述】:我的 C# 解决方案中有 3 个项目。
签名 结构 测试签名具有公共和内部接口。 此外,它有
[assembly: InternalsVisibleTo("Structures")]
[assembly: InternalsVisibleTo("Tests")]
在 AssemblyInfo.cs 中。
结构具有公共类和内部类,并且
[assembly: InternalsVisibleTo("Tests")]
在 AssemblyInfo.cs 中。
Tests 有下一个来源:
<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 的内部类编写了一个单元测试。运行,得到下一个结果:异常:
类型 Signatures.InterfaceX 对 DynamicProxy 不可见。无法为不可访问的类型创建代理。将类型设为 public 或 internal 并使用 [assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)] 属性标记您的程序集。
似乎合乎逻辑。我加了
[assembly: InternalsVisibleTo("InternalsVisible.DynamicProxyGenAssembly2")]
到签名和结构项目的装配信息。运行,得到下一个结果:异常:
程序集“DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”中的类型“Castle.Proxies.IReminiscenceableDataTableProxy”正在尝试实现无法访问的接口。
我希望它会有所帮助,但它没有。 它只是更改了异常消息。
如何解决我的问题?
【问题讨论】:
【参考方案1】:将以下内容添加到定义类的项目中的 csproj 文件中。
<ItemGroup>
<!-- For Moq to mock internal class objects -->
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
【讨论】:
【参考方案2】:在 .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 能够实例化该项目的内部类
【讨论】:
【参考方案3】:建议的修复消息使用 const/static 字段作为程序集名称:
[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]
您使用了与程序集名称不对应的字符串:
[assembly: InternalsVisibleTo("InternalsVisible.DynamicProxyGenAssembly2")]
改成:
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
您可以在错误消息中看到实际的程序集名称(应该出现在 InternalsVisibleTo
中):
从程序集“DynamicProxyGenAssembly2 (...) 中键入“Castle.Proxies.IReminiscenceableDataTableProxy”(...)
【讨论】:
这是一个重要的区别。抛出的错误消息让人认为我们需要第二个选项,但第三个实际上修复了它。 Castle Project 似乎暴露了一个const
成员,就像消息中的那个一样,请参阅 Castle.Core/Core/Internal/InternalsVisible.cs
,但似乎由于 Castle Project 嵌入在 Moq.dll
中的方式,这当通过 Moq 查看时,类变为非公开的,并且因为它不可访问,所以说 [assembly: InternalsVisibleTo(Castle.Core.Internal.InternalsVisible.ToDynamicProxyGenAssembly2)]
将不起作用。所以你必须拥有自己的魔线。
这对我不起作用,说强名称签名的程序集但包含公钥
此外,不可能对上述程序集进行混淆,所以 IMO 不是很好。以上是关于如何对 Moq 可见内部接口?的主要内容,如果未能解决你的问题,请参考以下文章