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

Streaming video asynchronously in ASP.NET Core 2 with Web API

 

Introduction

No matter what kind of project you are working on, at some point you will find the need to stream videos in your website or mobile apps for many purposes. So, we will learn how we can live stream our video content over HTTP, using ASP.NET Core 2 Web APIs.

Set up a service that get a Stream from a video hosted in the web using HttpClient

Example with videos hosted in Azure:

public class AzureVideoStreamService : IAzureVideoStreamService
{
   private HttpClient _client;

   public AzureVideoStreamService()
   {
      _client = new HttpClient();
   }

   public async Task<Stream> GetVideoByName(string name)
   {
      var urlBlob = string.Empty;
      switch (name)
      {
         case "earth":
         urlBlob = "https://anthonygiretti.blob.core.windows.net/videos/earth.mp4";
         break;
         case "nature1":
         urlBlob = "https://anthonygiretti.blob.core.windows.net/videos/nature1.mp4";
         break;
         case "nature2":
         default:
         urlBlob = "https://anthonygiretti.blob.core.windows.net/videos/nature2.mp4";
         break;
      }
      return await _client.GetStreamAsync(urlBlob);
   }

   ~AzureVideoStreamService()
   {
      if (_client != null)
      _client.Dispose();
   }
}
public interface IAzureVideoStreamService
{
   Task<Stream> GetVideoByName(string name);
}

Then don’t forget to register the service and it’s interface in Injection Dependency system

public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc();
   services.AddScoped<IAzureVideoStreamService, AzureVideoStreamService>();
}

Set up a Streaming controller that stream videos using FileStreamResult object

FileStreamResult sends binary content to the response using a Stream instance

Example of an API that return a video by its name:

[Route("api/[controller]")]
public class StreamingController : Controller
{
   private IAzureVideoStreamService _streamingService;

   public StreamingController(IAzureVideoStreamService streamingService)
   {
      _streamingService = streamingService;
   }

   [HttpGet("{name}")]
   public async Task<FileStreamResult> Get(string name)
   {
      var stream = await _streamingService.GetVideoByName(name);
      return new FileStreamResult(stream, "video/mp4");
   }
}

Run the Web API to test….

 

 

Easy isn’t it ? 😉

Injection Dependency: Bring your own container in .NET Core Web API, example with Simple Injector

Introduction of Simple Injector

Simple Injector is an easy-to-use Dependency Injection (DI) library for .NET that supports .NET Core, Xamarin, Mono and Universal apps. Simple Injector is easily integrated with frameworks such as Web API, MVC, WCF, ASP.NET Core and many others. It’s easy to implement the dependency injection pattern with loosely coupled components using Simple Injector.

Why Simple Injector? It’s simple to use, free, fast, support advanced generics types, and provide powerful diagnostics services.

If you want to know more about you can check the documentation here: https://simpleinjector.readthedocs.io/en/latest/quickstart.html

Installation of Simple Injector in ASP.NET Core WebAPI

Select and Install SimpleInjector.Integration.AspNetCore.Mvc from “Manage Nuget packages” panel

or type the following command in “Package manager console”:

Install-Package SimpleInjector.Integration.AspNetCore.Mvc -Version 4.0.12

Configuration of Simple Injector in ASP.NET Core WebAPI

  • Import SimpleInjector, SimpleInjector.Lifestyles and SimpleInjector.Integration.AspNetCore.Mvc namespaces
  • Add a Container property in your class Startup.cs
  • Register your service with its appropriate Interface, Simple Injector supports concrete injection (the class without its interface), you can set Lifestyle.Scoped, Lifestyle.Singleton or Lifestyle.Transient
  • Optionnally add Verify method,  (after RegisterMvcControllers method in Configure method) it iterates registered service to check if something is not correct, will throw an exception before any execution of the program
  • Add SimpleInjectorControllerActivator that implements IControllerActivator to provide dependency injection resolution in controllers constructor
  • Then add the extension method UseSimpleInjectorAspNetRequestScoping that ASP.NET requests into Simpleinjector’s scoped lifestyle

Example:

public interface IHelloWorldService
{
   string HelloWorld();
}
public class HelloWorldService : IHelloWorldService
{
   public string HelloWorld()
   {
      return "Hello world";
   }
}
[Route("api/[controller]")]
public class HelloController : Controller
{
   private IHelloWorldService _helloService;

   public HelloController(IHelloWorldService helloService)
   {
      _helloService = helloService;
   }

   [HttpGet]
   public string Get()
   {
      return _helloService.HelloWorld();
   }
}
public class Startup
{
   private Container container = new Container();

   public Startup(IConfiguration configuration)
   {
      Configuration = configuration;
   }

   public IConfiguration Configuration { get; }

   // This method gets called by the runtime. Use this method to add services to the container.
   public void ConfigureServices(IServiceCollection services)
   {
      services.AddMvc();

      // Default lifestyle scoped + async
      // The recommendation is to use AsyncScopedLifestyle in for applications that solely consist of a Web API(or other asynchronous technologies such as ASP.NET Core)
      container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

      // Register services
      container.Register<IHelloWorldService, HelloWorldService>(Lifestyle.Scoped); // lifestyle can set here, sometimes you want to change the default lifestyle like singleton exeptionally

      // Register controllers DI resolution
      services.AddSingleton<IControllerActivator>(new SimpleInjectorControllerActivator(container));

      // Wrap AspNet requests into Simpleinjector's scoped lifestyle
      services.UseSimpleInjectorAspNetRequestScoping(container);

  }

   // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
   public void Configure(IApplicationBuilder app, IHostingEnvironment env)
   {
      if (env.IsDevelopment())
      {
         app.UseDeveloperExceptionPage();
      }

      app.UseMvc();

      container.RegisterMvcControllers(app);

      // Verify Simple Injector configuration
      container.Verify();
   }
}

 

Execution:

 

We did it! we brought our own dependency injection container 🙂