assembly:InternalsVisibleToAttribute – Test Internal Methods

One of the problems with unit testing is that you can only test public accessible items within the assembly.  To solve this you have to make more items visible and increase your public interface in order to be able to unit test the item.  This is bad if you are planning on making your API useable outside of your own system as changing the public interface could cause breaking changes in other peoples’ systems.  It also means your internal system is exposed and useable to anyone.

The InternalsVisibleTo attribute solves this problem.  By including this within your AssemblyInfo.cs you can set which assemblies can access you internal items.  This means you can test your assembly without having to set everything to public.  You even get intellisense support with all of your internal methods listed.

If we have an assembly MyAPI which is tested by MyAPI.Tests.  If in our MyAPI.class we have the following code

public class MyPublicClass
{
    public bool IsValid()
    {
        return true;
    }

    private bool AllowedAction(string action)
    {
        if (string.IsNullOrEmpty(action))
            return false;

        return true;
    }
}

Which has the following test

[TestFixture]
public class MyPublicClassTests
{
    [Test]
    public void TestIsValid()
    {
        MyPublicClass cls = new MyPublicClass();
        Assert.IsTrue(cls.IsValid());
    }
}

In order for us to test the AllowedAction method we would have to make it public.  But then everyone using the API would be able to use it and we would be unable to refractor this method for the lifetime of the API.  By adding the attribute to the MyAPI.AssemblyInfo file and change the method from private to internal.

[assembly: InternalsVisibleTo(“MyAPI.Tests”)]

internal bool AllowedAction(string action)
{
    if (string.IsNullOrEmpty(action))
        return false;

    return true;
}

[Test]
public void TestActionAllowed()
{
    MyPublicClass cls = new MyPublicClass();
    Assert.IsTrue(cls.AllowedAction(“Test”));
}

This is great, we have only increased our public interface to our test method yet all the other assemblies cannot access it.  However, one problem with this is that if another malicious user came along with an assembly called MyAPI.Tests then they also would be able to access the internal actions.

Then is why it is recommend to sign the test assembly and include the public key within the attribute. In order to obtain the public key, you need to run the sn application on the assembly.

sn -Tp MyAPI.Tests.dll

The attribute would then look like this.

[assembly: InternalsVisibleTo(“MyAPI.Tests,PublicKey=00240000048…………de35d15ffae”)]

However, it means MyAPI must have a strong name/be signed.

An example of this being used is with the System.Data.Linq assembly, you can see that Microsoft use this attribute to allow the assembly to be tested by another assembly called DLinq.Unittests.

[assembly:InternalsVisibleTo(“DLinq.Unittests,PublicKey=########”)]

MSDN Link – http://msdn2.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

Technorati Tags: , ,