One of the hassles with testing is that best practices and OO design often makes it very difficult to thoroughly test your code. We should be marking classes internal to our assemblies unless we specifically wish them to be part of the public API of our DLL’s. This means to test these internal classes we have to use proxy classes that can instantiate and invoke members of these internal classes via reflection. Visual Studio provides for some auto-generated code for this, but it can be a bit unwieldy and is not available in all versions of VS. It would be easier if we could specify a test assembly as having access to all these internal classes.
Another case where we might want to make our internal classes available to specific outside callers is for security purposes. If we don’t want anyone but ourselves to use a specific DLL, we would want to mark all classes internal to the DLL and specify only those assemblies with our strong name have access to them.
The InternalsVisibleToAttribute allows us to do this. According to the documentation, the syntax is pretty easy:
<span>[</span><span style="color: navy;">assembly</span><span>: </span><span style="color: #2b91af;">InternalsVisibleTo</span><span>(</span><span style="background: #f3f8f3; color: green;">"MyTestsLol"</span><span>)]</span>
This would allow assembly MyTestsLol.DLL access to the internal classes of the assembly where this attribute is located. And this works great. For unsigned assemblies only. When you sign the assembly you wish to mark with this attribute, things get more complex.
Lets say you have two assemblies, My.DLL and MyTestsLol.DLL. You add the above attribute to the AssemblyInfo.cs file within the My.DLL project. Everything works great; you can access and test all internal classes in My from within MyTestsLol. But you’re moving to a production oriented environment and you decide that you should be signing your assemblies, because you’ve read that’s what professional .NET developers do. So you sign My.DLL and build the project:
Friend assembly reference ‘MyTestsLol’ is invalid. Strong-name signed assemblies must specify a public key in their InternalsVisibleTo declarations.
Now you’re screwed. And if you Google this, you’ll still be screwed because most of the information about InternalsVisibleTo and strong named assemblies is either wrong or too cryptic to understand. If you find yourself at this point, here is the step-by-step procedure how to get this working again.
Gimme three steps to fix
First, you will need to sign every assembly you wish to grant access to your internals. Open up the properties editor for the assembly you wish to give access to, in this case MyTestsLol.DLL, and select the Signing tab.
I’d suggest creating a new, throw-away key pair for test assemblies. For assemblies you are going to distribute you should use your regular key pair.
Second, you must extract the public key from the public/private key pair, then display the public key. This is a two-part process that is necessary in order to get the correctly encoded version of the public key.
Open the Visual Studio command prompt (All Programs -> Visual Studio 2005/8 -> Visual Studio Tools). Browse to the directory where the new public/private key pair is located. At the prompt, enter the following command (the name of the key pair (.snk) may be different if you chose a different name for the strong name key file):
sn -p fortestsonly.snk publickey.pub
This creates a file, called publickey.pub, that contains the public key portion of the public/private key pair in binary format. Next, you need to view the public key in an encoded format (I believe its Base64) that you can use. Do this via the following command:
sn -tp publickey.pub
This displays both the full public key and the public key token, which is a much smaller hash of the full public key. You’ll need the full public key (the token will not work), so select it and copy it out of the console. Consoles suck, so you’ll have to remove all the newline’s when you paste it into your assembly.
Finally, adjust your InternalsVisibleTo argument to add the public key (the public key should reside on a single line and be roughly three hundred something characters long):
<span>[</span><span style="color: navy;">assembly</span><span>: </span><span style="color: #2b91af;">InternalsVisibleTo</span><span>(</span><span style="background: #f3f8f3; color: green;">"MyTestsLol, </span>
<span style="background: #f3f8f3; color: green;"> PublicKey=0024...8db5"</span><span>)]</span>
The ellipsis is just to keep the key from blowing up my blog’s layout.
This will now work, and you can reference internal types from the MyTestsLol assembly. Unfortunately, there isn’t an equivalent attribute you can place on a type to allow its internals be visible to another type or another assembly, which would have made unit testing private methods a snap. I’m not sure exactly why we don’t have this kind of facility in the .NET platform. Maybe in 4?