LP on .NET

January 2, 2012

Using Internal Interfaces with Moq

Filed under: .NET,C# — Larry Parker @ 4:10 pm

Lately I’ve been using the C# internal modifier more and more for code that I intend to keep, well, internal to my assembly.  This has especially been the case for framework code that I have been writing that will not be accessed by framework consumers.  The internal modifier lets others know that it’s internal implementation, subject to change, hands off, etc.

But one area of my code that I’ve had to begrudgingly keep public has been internally used interfaces because they could not be tested with Moq.  They compile just fine.  It’s just that Moq gives me a runtime error:  Castle.DynamicProxy.Generators.GeneratorException: Type <whatever> is not public. Can not create proxy for types that are not accessible.

But before I get into the details, why would you want to use an internal interface anyway?  Aren’t interfaces by definition supposed to be public?  Well I guess if that were the case then Microsoft wouldn’t allow you to apply the internal modifier to them.  🙂

But seriously, consider the case where you’re doing dependency injection where you hand a class a bunch of interface references in its constructor, but these interfaces are just internal to the assembly.  In other words, you’re writing testable code with injected interfaces to facilitate unit testing.  Just because they’re interfaces doesn’t mean you intend to publish them externally.  Hence the use of internal interfaces.

As an example, say you have a customer manager with an AddCustomer method that calls a persistence layer to add the customer to the database.  The code might look like this:

internal class CustomerManager {
    public CustomerManager(ICustomerPersistence customerPersistence)
    {
        _customerPersistence = customerPersistence;
    }

    private ICustomerPersistence _customerPersistence;

    public void AddCustomer(String customerName)
    {
        _customerPersistence.Add(customerName);
    }
}

internal interface ICustomerPersistence {
    void Add(String customerName);
}

Both the CustomerManager class and the ICustomerPersistence interface are marked as internal because they won’t be used outside the current assembly.  When we create our unit test for the AddCustomer method via Visual Studio’s Create Unit Tests… context menu option, it makes our unit test assembly a “friend” of the assembly containing the CustomerManager class:

[assembly: InternalsVisibleTo("CustomerTest, PublicKey=...")]

 

Now let’s write a unit test for the AddCustomer method that mocks the ICustomerPersistence interface:

[TestMethod()]
public void AddCustomerTest()
{
    var customerPersistenceMock = new Mock<ICustomerPersistence>();

    CustomerManager target = new CustomerManager(customerPersistenceMock.Object);

    String name = "Sue Jones";
    target.AddCustomer(name);
    customerPersistenceMock.Verify(o => o.Add(name));
}

This compiles ok, but when we run the test we get the error mentioned above; i.e. that the ICustomerPersistence interface is not public and that Moq cannot create a proxy for it.

My workaround for this has been to grit my teeth and make the interface public:

public interface ICustomerPersistence {
    void Add(String customerName);
}

But once you do that, developers start asking you what the ICustomerPersistence interface is for (it’s public after all), how they should be using it, where is the documentation, etc.  All these problems because you just wanted to write a unit test that mocks the interface.  🙂

Fortunately, there’s a solution.  You just need to use the InternalsVisibleTo assembly attribute to make Moq a friend of the assembly containing the internal ICustomerPersistence interface.

Unfortunately, the Moq assembly name wasn’t so obvious and I couldn’t find it in the Moq documentation.  But after some searching, I found a couple of blog posts on it.  Since Moq is a signed assembly, you need to provide the public key to the InternalsVisibleTo attribute.  The tricky part is copying the public key correctly, and some of the blogs posts either had it wrong or had it formatted such that copying and pasting didn’t work properly.

But this blog post got it right: 

http://blog.ashmind.com/category/agile/mocking/

I’ll post the code here too, and I hope you’ll be able to copy and paste it into your own AssemblyInfo.cs file (you’ll need to scroll to the right to get the entire public key):

// Make internal interfaces visible to Moq [assembly:InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 

 

Now I was able to change all of those public interfaces back to internal, which made my code just a little bit cleaner.

Hope this helps.

Advertisements

2 Comments »

  1. Nice article. I’ll also add that the public key is not required. Adding [assembly:InternalsVisibleTo(“DynamicProxyGenAssembly2”)] to assembly.info is sufficient.

    Comment by Ryan — August 27, 2012 @ 5:24 pm | Reply

  2. Lovely – helped me out for a second time

    Comment by Paul Hodgson — September 26, 2013 @ 9:08 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: