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

 

 

How to run unit tests in a VSTS CI build with Angular 5 and PhantomJS Part 1

Setting up Angular 5 project

You chose Angular 5 as FrontEnd framework, and you made a good choice!

As you can see, Angular 5 comes with Angular-CLI 1.5.

Angular-CLI  npm package installs Angular 5 as we said before and also a complete unit tests toolset :

  • Karma
  • Jasmine

Karma is a Javascript test runner, and Jasmine is a behavior-driven development framework for testing JavaScript code.

In this article I won’t describe how they work, but i will describe how to use then in a VSTS CI.

The critical phase we encounter is how unit tests are run: Karma need a browser to run units tests with Jasmine .

With Angular-CLI there is no issue with that because when you launch your tests with :

ng test

Karma launches automatically a browser like this :

Now we want to build a CI in VSTS but, there is no browser! what can we do ?

PhantomJS is here to help us!

PhantomJS is a so called Headless Browser (or headless WebKit scriptable, as they call it themselves). A headless browser is a browser that is just running in the background, that you can only interact with via code or a terminal. This is just what we need, so let’s make our test run on Phantom instead of Chrome.

WOW!

how does it work ?

Let’s install it and set up in our Angular 5 project!

Step 1, install PhantomJS itself and its runner for Karma

npm install phantomjs-prebuilt --save-dev
npm install karma-phantomjs-launcher --save-dev

Step 2, add them by modifying karma.conf.js

Add karma-phantomjs-launcher in plugins array :

plugins: [
 require('karma-jasmine'),
 require('karma-chrome-launcher'),
 require('karma-phantomjs-launcher'), 
 require('karma-jasmine-html-reporter'),
 require('karma-coverage-istanbul-reporter'),
 require('@angular/cli/plugins/karma')
 ],

Step 3, uncomment the big pollyfils block in pollyfils.ts :

import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';

import 'intl'
import 'intl/locale-data/jsonp/en'

Step 4, Add a ng test script in package.json :

"scripts": {
 "ng": "ng",
 "start": "ng serve",
 "build": "ng build",
 "test": "ng test",
 "lint": "ng lint",
 "e2e": "ng e2e",
"test-single-headless": "ng test --single-run=true --browsers=PhantomJS --reporters=progress"
 },

We are done for the PhantomJS setting up! 🙂

Let’s take a look on VSTS configuration for CI

How to run unit tests in a VSTS CI build with Angular 5 and PhantomJS Part 2

<< Previous article (Part 1)

Configure VSTS CI build for Angular 5 projects

We saw previously how to configure our projet to make the CI running properly in VSTS.

Now let’s see each steps to configure our CI build to making running unit tests with PhantomJS.

All following steps use npm tasks and I will use npm commands, not NG

Step 1, install Angular-CLI globally

This step is not required if you installed the CLI locally like me, because i want to be able to work with different versions depending project i’m working on.

Set up as follow the installation :

Step 2, install project dependencies

Step 3, install project dependencies

Build the project

Step 4, run the tests

Choose here custom task and set as command the command we defined earlier in the project in scripts block of packages.json

"scripts": { 
"ng": "ng", 
"start": "ng serve", 
"build": "ng build", 
"test": "ng test", 
"lint": "ng lint", 
"e2e": "ng e2e", 
"test-single-headless": "run test --single-run=true --browsers=PhantomJS --reporters=progress" 
},

That’s it!

Now your output should look like this :

 

Awesome isn’it ? 😉