How to unit test private methods in .NET Core applications? (even if it’s bad)

Introduction

Yes it’s bad and dirty!

Since your private methods are only an implementation detail whose existence and behavior is only justified by their use in public methods, then these private methods are automatically tested through public method tests.

In other words, once your public methods are tested, your private methods should be fully covered. If this is not the case, it is either that you have forgotten tests or that your private method does things that are of no use to meet the needs of your public methods. In this case, it is probably necessary to clean them.

“Yes, but my private methods are big and complicated, tests would be very practical Sometimes, we see private methods that are full of stuff or things so complicated, that having tests would still be very practical.”

That is true. We see some.

Even myself I have been I was confronted with this kind of problem:

“Sometimes a bug is located in a private method and I do not want to recreate all the context necessary to call the public method.”

That’s why I’m going to show you how to test them, but do not forget that this should be truly exceptional.

How to?

This is really more simple than you think! we will just use Reflection.

In this example, I will use XUnit and FluentAssertion.

Let’s define a class with a private method:

namespace XUnitAndFluentAssertionDemo
{
   public 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")
      {
      }
   }
}

Now let’s write the unit test using Reflection:

We will use the well known function Activator.CreateInstance and fetch its methods and properties using Linq, then invoke the method to test with the well known method Invoke:

namespace UnitTests
{
   public class HelloTests
   {
      [Fact]
       public void PrivateHelloManShouldBeWellFormated()
       {
          // Arrange
          var firstName = "John";
          var lastName = "Doe";

          Type type = typeof(Hello);
          var hello = Activator.CreateInstance(type, firstName, lastName);
          MethodInfo method = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
          .Where(x => x.Name == "HelloMan" && x.IsPrivate)
          .First();

          //Act
          var helloMan = (string)method.Invoke(hello, new object [] {firstName, lastName});

         //Assert
         helloMan
         .Should()
         .StartWith("Hello")
         .And
         .EndWith("!")
         .And
         .Contain("John")
         .And
         .Contain("Doe");
       }
    }
}

Conclusion

Wondering “how to test a private method” should raise an alarm.

You should first find a solution to avoid this, review your code, but often it’s not easy because you maintain very old legacy code or your colleagues are stubborn :).

Anyway, I hope this article would help you.

Good luck 🙂

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? 😉

Code reliability: Unit testing with XUnit and FluentAssertions in .NET Core 2 apps

Introduction

I decided to write this article because I’m really fan of XUnit and FluentAssertions expecially for its great syntax.

Xunit

xUnit.net is a free, open source, community-focused unit testing tool for the .NET Framework. Written by the original inventor of NUnit v2, xUnit.net is the latest technology for unit testing C#, F#, VB.NET and other .NET languages. xUnit.net works with ReSharper, CodeRush, TestDriven.NET and Xamarin. It is part of the .NET Foundation, and operates under their code of conduct. It is licensed under Apache 2 (an OSI approved license).

FluentAssertions

FluentAssertions is the best assertion framework in the .NET realm.

FluentAssertions supports the following .NET versions:

  • .NET 4.0, 4.5 and 4.6
  • CoreCLR, .NET Native, and Universal Windows Platform
  • Windows Store Apps for Windows 8.1
  • Silverlight 5
  • Windows Phone 8.1
  • Windows Phone Silverlight 8.0 and 8.1
  • Portable Class Libraries

Fluent Assertions supports the following unit test frameworks:

 

Setup your .NET Core 2 project

Install XUnit

Download it via Nuget package manager:

Or type this command in Nuget package manager console:

PM> Install-Package xunit -Version 2.3.1

Install XUnit Visual Studio runner

This package allow to Visual Studio to discover XUnit unit tests, if you don’t install it, Visual Studio won’t detect them.

Download it via Nuget package manager:

Or type this command in Nuget package manager console:

PM> Install-Package xunit.runner.console -Version 2.3.1

Install FluentAssertions

Download it via Nuget package manager:

Or type this command in Nuget package manager console:

PM> Install-Package FluentAssertions -Version 5.0.0-rc0002

 

Write your unit tests

Example of a class to unit test:

public 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 $"Hello {_firstName} {_lastName} !";
   }

   public string Your()
   {
      return $"Hello {_firstName} {_lastName} !";
   }
}

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

Example of a related Unit tests class:

public class HelloTests
{
   [Fact]
   public void HelloManShouldBeWellFormated()
   {
      // Arrange
      var hello = new Hello("John", "Doe");

     //Act
     var helloMan = hello.HelloMan();

     //Assert
     helloMan
     .Should()
     .StartWith("Hello")
     .And
     .EndWith("!")
     .And
     .Contain("John")
     .And
     .Contain("Doe");
   }

   [Fact]
   public void HelloManShouldBeRaiseExceptionWhenFirstNameIsNotSet()
   {
      // Arrange
      var hello = new Hello("", "Doe");

      //Act
      Action actionHelloMan = () => hello.HelloMan();

      //Assert
      actionHelloMan
      .Should()
      .Throw<MissingFirstNameException>()
      .WithMessage("FirstName is missing");
   }
}

 

Now just run your test with “Test” menu in Visual Studio:

 

That’s it!

Cute unit testing isn’t it? 😉