62

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?

Valentyn Zakharenko
  • 2,710
  • 1
  • 21
  • 47

4 Answers4

110

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 (...)

PerryC
  • 1,233
  • 2
  • 12
  • 28
k.m
  • 30,794
  • 10
  • 62
  • 86
  • This is an important distinction. The error message thrown leads one to think we need the second option, but the third one actually fixes it. – SouthShoreAK Jan 14 '16 at 16:49
  • 6
    It seems the Castle Project exposes a `const` member like the one from the message, see [`Castle.Core/Core/Internal/InternalsVisible.cs`](https://github.com/castleproject/Core/blob/master/src/Castle.Core/Core/Internal/InternalsVisible.cs), but it appears that because of the way Castle Project is embedded inside the `Moq.dll`, this class becomes non-public when seen through Moq, and because it is not accessible, saying `[assembly: InternalsVisibleTo(Castle.Core.Internal.InternalsVisible.ToDynamicProxyGenAssembly2)]` will not work. So you must your own magic string. – Jeppe Stig Nielsen Feb 23 '16 at 15:59
  • 1
    this does not work for me, says strong name signed assemblies but include a public key – Alex Gordon Aug 18 '17 at 02:08
  • Besides, obfuscation of the said assembly won't be possible so, not great IMO. – CTZStef Oct 29 '20 at 20:10
11

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 Moq to instanciate internal classes of that project
Martin
  • 5,165
  • 1
  • 37
  • 50
7

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>
DanKodi
  • 3,550
  • 27
  • 26
4

In .NET 5, the following can be added to .csproj

<ItemGroup>
  <InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>

Source: https://github.com/dotnet/sdk/pull/3439

Source: https://stackoverflow.com/a/66055829/4503491

Red Riding Hood
  • 1,932
  • 1
  • 17
  • 36