How to do internal interfaces visible for Moq?

C#Unit TestingNunitMoqInternals

C# Problem Overview


I have 3 projects in my C# solution.

  • Signatures
  • Structures
  • Tests

Signatures have public and internal interfaces. Also, it has

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

in AssemblyInfo.cs of.

Structures have public and internal classes and

  [assembly: InternalsVisibleTo("Tests")]

in AssemblyInfo.cs of.

Tests has next source:

<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>

as NuGet packages in packages.config.

I wrote an unit test for the internal interface from Signatures and internal class from Structures. Run, and had next result: exception:

Type Signatures.InterfaceX is not visible to DynamicProxy. Can not create proxy for types that are not accessible. Make the type public, or internal and mark your assembly with [assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)] attribute.

Seems logical. I added

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

to assembly info of Signatures and Structures projects. Run, and had next result: exception:

Type 'Castle.Proxies.IReminiscenceableDataTableProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is attempting to implement an inaccessible interface.

I expected it would help but it didn't. It only changed the exception message.

How to fix my problem?

C# Solutions


Solution 1 - C#

The suggested fix message uses a const/static field for the assembly name:

[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)]

You used a string which does not correspond to the assembly name:

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

Change it to:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 

You can see the actual assembly name (which should appear in InternalsVisibleTo) in your error message:

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

Solution 2 - C#

Add the below to the the csproj file in the project where the classes are defined.

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

Solution 3 - C#

In .Net Core / .NET 5 you can also combine user DanKodi's answer with this article, so you do not need to set the assembly attribute anywhere.

Just edit the production code .proj file that contains the code you want to test like this:

<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>


This does the following:

  • It makes the assembly visible to the project that contains the tests (as long as the name of the test project is the name of the project you want to test with an ".Tests" suffix)
  • It enables mock to instanciate internal classes of that project

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionValentine ZakharenkoView Question on Stackoverflow
Solution 1 - C#k.mView Answer on Stackoverflow
Solution 2 - C#DanKodiView Answer on Stackoverflow
Solution 3 - C#MartinView Answer on Stackoverflow