Unit Testing Non-Public Classes from a Separate Assembly

Segmenting unit tests from release code by placing the tests in a separate assembly (e.g. in a separate Microsoft Visual Studio project) is a good idea. However, making release code classes public in order to allow the unit test assembly to access them isn’t a good practice.

In C#, a class’s accessibility level defaults to internal—only code located in the same assembly as the class is allowed to reference the class. If code located elsewhere (such as in a separate unit test assembly) attempts to reference the class, compilation will fail with the error “‘ClassToBeTested ‘ is inaccessible due to its protection level“.

One way to resolve this dilemma is to make the relevant release code classes public (“public class ClassToBeTested { /* … */ }“). If the developer is being thorough in testing, this approach will require that almost all classes be made public, in effect defeating the purpose of class access control.

Is there a better solution? Yes!

Friend Assemblies

Code in a friend assembly is allowed to access the befriending assembly’s internal classes. In C#, the befriending assembly grants this privilege via the InternalsVisibleTo attribute. The attribute’s argument consists of the to-be-friended assembly’s name and, in the case of a signed assembly, the to-be-friended assembly’s public key. The attribute is placed in the befriending assembly in either AssemblyInfo.cs or at the beginning of any source code file.

// In assembly MyApplication
[assembly: InternalsVisibleTo("UnitTests")]

With this assembly-wide directive in place, the unit test project may now use internal classes in the release code assembly, eliminated the need for those classes to be made public solely to facilitate testing.

Leave a Reply

Your email address will not be published. Required fields are marked *