SHARE:

How to unit test Internal classes in .NET Core applications?

Introduction

The creation of unit tests is an important step in ensuring the quality of a project. In general, most public methods are tested, but what if you want to test a non-public part of the project?

Putting all classes of your .Net project in public is not recommended. From the moment when you reference your assembly in a project in Visual Studio, you will have access to all your classes, methods, properties and fields marked as public, and there are surely parts of your code that it is not worth better not leave accessible because they could change the behavior of the assembly or have any negative impact. This is why the keywords “internal” and “private” exist. Only then, your non-public types and members can not be called directly from your unit tests because (in principle) your tests are in separate assemblies.

Fortunately, there is a solution for testing non-public types and members, specifically, internal.

In this article I will show you how to achieve our goals.

We will use an attribute, InternalsVisibleTo, which will make it possible to specify that a particular assembly will have access to the types and members marked as being internal of the current assembly.

Solution

Let’s define an internal class to test like this named “Hello

namespace XUnitAndFluentAssertionDemo
{
   internal class Hello
   {
      private string _firstName { get; set; }
      private string _lastName { get; set; }

      public Hello(string firstName, string lastName)
      {
         _firstName = firstName;
         _lastName = lastName;
      }

      public string HelloMan()
      {
         if (string.IsNullOrEmpty(_firstName))
            throw new MissingFirstNameException();

         return this.HelloMan(_firstName, _lastName);
      }

      private string HelloMan(string firstName, string lastName)
      {
         return $"Hello {firstName} {lastName} !";
      }
   }

   public class MissingFirstNameException: Exception
   {
       public MissingFirstNameException(): base("FirstName is missing")
       {
       }
   }
}

 

Then let’s try to test it in a Unit testing project:

As you can see, it doesn’t work the “UnitTest” project can’t see the internal class

Now let’s add [assembly: InternalsVisibleTo(“UnitTests”)] as decorator on the namespace, it should solve our problem now 🙂

[assembly: InternalsVisibleTo("UnitTests")]
namespace XUnitAndFluentAssertionDemo
{
   internal class Hello
   {
      private string _firstName { get; set; }
      private string _lastName { get; set; }

      public Hello(string firstName, string lastName)
      {
         _firstName = firstName;
         _lastName = lastName;
      }

      public string HelloMan()
      {
         if (string.IsNullOrEmpty(_firstName))
            throw new MissingFirstNameException();

         return this.HelloMan(_firstName, _lastName);
      }

      private string HelloMan(string firstName, string lastName)
      {
         return $"Hello {firstName} {lastName} !";
      }
   }

   public class MissingFirstNameException: Exception
   {
       public MissingFirstNameException(): base("FirstName is missing")
       {
       }
   }
}

 

Beautiful isn’t it? 😉

Written by

anthonygiretti

Anthony is a specialist in Web technologies (14 years of experience), in particular Microsoft .NET and learns the Cloud Azure platform. He has received twice the Microsoft MVP award and he is also certified Microsoft MCSD and Azure Fundamentals.