32
votes

I have a C# project and a test project with unit tests for the main project. I want to have testable internal methods and I want to test them without a magical Accessor object that you can have with Visual Studio test projects. I want to use InternalsVisibleToAttribute but every time I've done it I've had to go back and look up how to do it, which I remember involves creating key files for signing the assemblies and then using sn.exe to get the public key and so on.

  • Is there a utility that automates the process of creating a SNK file, setting projects to sign the assemblies, extracting the public key, and applying the InternalsVisibleTo attribute?

  • Is there a way to use the attribute without signed assemblies?

3

3 Answers

40
votes

You don't have to use signed assemblies to use InternalsVisibleTo. If you don't use signed assemblies, you can just enter the full name of the assembly.

So if you want to have access to MyAssembly in you test assembly (MyAssembly.Test) all you need in AssemblyInfo.cs for MyAssembly is the name of the test assembly like this:

[assembly: InternalsVisibleTo("CompanyName.Project.MyAssembly.Test")]
14
votes

Brian is right, but, offcourse in some cases you do have a signed assembly, and you do want to get the public key of that assembly.

Getting this key is indeed quite a hassle.
Therefore, I've done this:
I've customized my external tools in VS.NET, so that I can get the public key of the assembly of the current project with just one click of the mouse.
This is how it's done:

  • In VS.NET, open the 'Tools' menu, and click on 'External Tools'
  • A window that is called 'External tools' will open
  • Click on Add
  • For title, type in 'Get public key'
  • In 'Command', type in C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sn.exe
  • In 'Arguments', type: -Tp $(TargetPath)
  • Make sure you check the 'Use output window' option

Then, you build the project, and when you click on 'Get public key', you should see the public key for this project in the output window.

3
votes

There is another alternate to call internal methods and that is using "Reflection".

        BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;

        MethodInfo minfo = typeof(BaseClassName).GetMethod("MethodName", bindingFlags);
        BaseClassName b = new BaseClassName();            
        minfo.Invoke(b, null);

Here I assumes that "BaseClassName" is name of the class from another classlibrary and "MethodName" is name of internal method.