Mocking internal interfaces

Yesterday I’ve worked on connector library used to access data warehouses provided by two external vendors. In order for it to be easy to use I limited public members to:

  • library interface – can be used to aggregate connectors and testing
  • two connector classes that provide public methods to retrieve prepared responses
  • DTO request and response classes

In the project, there are several more interfaces and additional classes required to properly retrieve, process and present data. I didn’t want to obscure usability of the library, so I decided to mark all of them as internal. And obviously, there were problems with it:

  1. accessing the internal method from test projects
  2. the mocking of an internal interface in tests

The solution wasn’t difficult and writing it down seems like the good start of a new year.

1. Accessing the internal method from Tests project

If you try to access internal void InternalMethod() from test assembly (which I assume is different than assembly where method exists), the compiler will give you following error:

'InternalMethod()' is inaccessible due to its protection level

What you can do is either change the method back to being public (obviously not what we want) or add the following line at the beginning of any file in the assembly where method exists:

[assembly: InternalsVisibleTo("InterfaceAssembly.Tests")]

The interesting thing is that this line is global for entire assembly (which is obvious when you read it). There is no need to copy it to every file with internal class or method.

Furthermore, you can narrow down assembly and provide it’s Public Key Token as an additional security measure, but I don’t think it can actually prevent a skilled hacker from accessing them for long.

2. Mocking of internal interface

If you try to use Moq library to mock internal interface you will be facing even longer error message (but with the partial solution already embedded inside):

Castle.DynamicProxy.Generators.GeneratorException : 
Can not create proxy for type Moq.IMocked`1[[IInternalInterface, InterfaceAssembly, ...]] 
because type InterfaceAssembly.IInternalInterface is not accessible. 
Make it public, or internal and mark your assembly with 
[assembly: InternalsVisibleTo(InternalsVisible.ToDynamicProxyGenAssembly2)] 
attribute, because assembly Moq is strong-named.

It would seem that simply adding

[assembly: InternalsVisibleTo("InterfaceAssembly.Tests"),

would solve the problem, but that didn’t happen in my case. On the contrary, the error message because much more obscure:

System.ArgumentException : Type to mock must be an interface or an abstract or non-sealed class.
  ----> System.TypeLoadException : Type 'Castle.Proxies.ObjectProxy' from assembly 'DynamicProxyGenAssembly2, ...' is attempting to implement an inaccessible interface.[/code]

As it turns out, the static variable InternalsVisible.ToDynamicProxyGenAssembly2 embeds Public key token that doesn’t match the one on DynamicProxyGenAssembly2. Therefore I was required to fall back to just assembly name

[assembly: InternalsVisibleTo("InterfaceAssembly.Tests"),

And henceforth my tests are running and users are not overwhelmed by the abundance of internal (and therefore a bit useless) classes.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s