.Net core library: How to test private methods using xUnit

For testing internal classes, @Patric's answer is correct.

Private methods are private for a good reason, supposedly. They should not become internal, again for a good reason.

(And some ppl argue that we should not write unit tests for private methods. Why? Well, because they are "private"! But if you are so serious to write unit tests for private methods:)

This is a much better way to test private methods:

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 Exception("Missing First Name.");
    return this.HelloMan(_firstName, _lastName);
  }

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

The test goes like:

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");
   }
 }

Reference:

http://anthonygiretti.com/2018/08/26/how-to-unit-test-private-methods-in-net-core-applications-even-if-its-bad/


A quick solution is to make private members that you want to test internal.

You can then add an InternalsVisibleTo attribute to your main library's AssemblyInfo.cs. This will allow your test library (and no other library, without reflection) access to the internal methods/classes in your main library.

e.g.

[assembly: InternalsVisibleTo("Library.Tests")]