Archives mensuelles : janvier 2015

.NET : Améliorez vos tests unitaires avec Moq et NFluent

Une des bonnes pratiques d’un projet informatique est la mise en place de tests unitaires. Je vais vous présentez 2 librairies, disponible sous forme de package NuGet, pour vous aidez dans l’écriture de tests.

Moq

Le but d’un test unitaire est de tester un composant isolé, d’où la nécessité d’utiliser une librairie permettant de faire du Mock. J’utilise pour cela Moq.

Les exemples de tests suivant utilisent NUnit comme framework de tests unitaires. Afin de pouvoir facilement remplacer les dépendances des classes à tester, j’utilise Unity comme container d’injection de dépendance (IoC). Vous allez ainsi pouvoir facilement passer à votre classe dans le constructeur votre Mock.

Voyons comment configurer et effectuez des assertions sur vos mock avec Moq :

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using NFluent;
using NUnit.Framework;

namespace Demo.Tests
{
    [TestFixture]
    public class MyServiceTests : BaseServicesTests
    {
        private Mock<IMyService> myServiceMock;
        private Mock<ILogger> loggerMock;
        
        private IMyClass myClass;

        [SetUp]
        public override void SetUp()
        {
            base.SetUp();

            //Create Mocks
            myServiceMock = new Mock<IMyService>();
            loggerMock = new Mock<ILogger>();
                                  
           //We pass our mock to the instance to test
           myClass = new MyClass(myServiceMock, loggerMock);
        }

        [Test]
        public void MyMethodShouldReturnTrue()
        {
            //Setup method on service to return expected value to test our case
            //Here we setup to return an empty list of string
            myServiceMock.Setup(m => m.GetData()).Returns(new List<string>());
            
            var result = myClass.MyMethod();
            //Verify the result is what is expected
            Check.That(result).IsTrue();
            //Verify that our mock has been called
            myServiceMockSetup.Verify(m => m.GetData(), Times.Once);
        }
    }
}

Moq fournit un ensemble de méthodes permettant de configurer (Setup + Returns/Callbacks) et d’effectuer des tests sur les mocks (Verify).
On peut par exemple vérifier le nombre d’appel d’une méthode, les paramètres, …

Voici comment vérifier qu’un méthode prenant un paramètre de type string a bien été appelé 2 fois avec comme valeur de paramètre « MyTestString »

myServiceMock.Verify(r => r.MyMethod(It.Is<string>(x => x == "MyTestString")), Times.Exactly(2));

Le guide de démarrage de Moq

NFluent

Comme vous avez pu peut être le remarquer, je fais pas mal de JavaScript en ce moment et j’aime beaucoup les librairies de tests style jasmine, should, … qui permettent de décrire les assertions de manière plus lisibles. En .Net, j’utilise NFluent qui permet d’avoir une API d’assertion fluent où l’on peut chaîner les assertions à la suite les une des autres.

Check.That(julien)
    .IsNotNull()
    .And.IsNotEqualTo(david)
    .And.IsInstanceOf<Person>();

Dans l’exemple ci-dessus, je vérifie que le l’objet julien n’est pas null, n’est pas égal à david et que cet objet est une instance de la classe Person.

D’autres exemples d’assertions :

//Collections
//Nombre d'élément d'une collection
Check.That(persons).HasSize(3); 
//Il existe une personne ayant la propriété Name égale à Julien
Check.That(persons.Extracting("Name")).Contains("Julien"); 

//Test des exceptions
Check.ThatCode(() => myService.MyMethod())
    .Throws<MyException>()
    .WithMessage("MyMessage")
    .And.WithProperty("MessageKey", "MyMessageKey");

Voici des exemples d’assertion avec NFluent.

Liens

Bon tests 🙂 …

ES6 : quelques nouveautés de la prochaine version de JavaScript – Part II

Cet article est la suite de ES6 : quelques nouveautés de la prochaine version de JavaScript.

Modules

La gestion de modules/dépendances est un vrai manque dans JavaScript. Des solutions comme AMD ou CommonJs ont permis de combler ce manque. La nouvelle version de JavaScript apporte une gestion native des modules.

Un module est défini dans un fichier. Les fonctions de ce fichier ne sont pas visibles des autres fichier à moins de les exporter explicitement. Cela se fait via l’introduction de 2 nouveaux mots clés : import et export. Export permet de définir ce que vous voulez exposer. A l’opposé,  import permet de d’importer tout ou partie d’un module.

Déclarons un fichier utils.js qui contient une fonction permettant de générer un Uuid

function generateUUID () {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r &amp;amp; 0x3 | 0x8);
        return v.toString(16);
    });
};

export { generateUUID }

Importons la méthode generateUUID dans un autre module

import { generateUUID } from 'utils';

var uuid = generateUUID();

On peut même importer le module complet

import 'utils' as utils;
 
console.log(utils.generateUUID());

Quelques liens pour aller plus loin :

Angular 2.0 utilisera les modules ES6.

Classes

ES6 apporte la gestion des classes via le mot clé class (avec d’autres comme constructor et extends). JavaScript est déjà objet via les prototypes mais peu de gens savent les utiliser.
Les nouveaux mots clés sont juste du « sucre syntaxique » au dessus des prototypes afin de faciliter l’écriture sous forme de classes, plus familier des personnes venant de Java, C#, ….

Pour ceux qui s’intéressent au développement objet via les prototypes, je conseille la présentation de Christophe Porteneuve, portant notamment sur les prototypes, à Paris Web : slides et vidéo.

Voici un exemple de la définition d’une classe Employee héritant de Person.

class Person {
    constructor(firstName, lastName, age) { //constructors!
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    fullName(){
        console.log(this.firstName + &amp;quot; &amp;quot; + this.lastName);
    }
}

class Employee extends Person { //inheritance
    constructor(firstName, lastName, age, salary) {
        super(firstName, lastName, age); //call the parent constructor with super
        this.salary = salary;
    }

    printSalary(){
        console.log('Salary : ' + this.salary);
    }
}

let julien = new Employee('Julien', 'Roy', '33', 150000);

julien.fullName();
julien.printSalary();

Quelques liens pour aller plus loin avec les classes ES6.

Améliorations sur les objets

ES6 apporte également des raccourcis concernant la création d’objet concernant :

la création de méthode

//ES5
var obj = {
        myMethod: function () {
            ···
        }
    };
//ES6
var obj = {
        myMethod() {
            ···
        }
    };

les propriétés

Il n’est plus necessaire de spécifier la valeur si on créer une propriété à partir d’une variable.

let x = 4;
let y = 1;
let obj = { x, y }; //ES6
let es5Obj = { x : x; y : y};

Computed property keys

Il est maintenant possible de créer des propriétés ayant une clé composé lors de la création d’un objet.

let obj = {
        [propKey]: true,
        ['b'+'ar']: 123
    };

De nouvelles méthodes sont également disponible :

Object.is()

Object.is permet une comparaison supprimant des cas bizarres en js lors des comparaison avec ===

(NaN !== NaN) //false 
-0 === +0 //false
var isSame = Object.is(value1, value2);

Object.assign()

La méthode assign permet la copie les propriétés d’un objet source dans un autre objet (idéal pour les options par défaut ou le clone d’objet).
Cette méthode existait dans plusieurs librairies comme $.extend en jQuery ou _.defaults pour Underscore/lodash.

Exemple de copie d’un objet avec Object.assign()

var obj = { a: 1 };
var copy = Object.assign({}, obj);

Quelques liens pour aller plus loin :

Symbols

ES6 apporte un nouveau type primitif : les Symbols. Ils sont uniques (2 symbols ne sont jamais égaux) et immutables (non modifiables). Ils peuvent être utilisés pour définir une propriétés d’un objet par exemple (on utilisera la méthode Object.getOwnPropertySymbols() pour obtenir les propriétés de type symbole d’un objet).

//Création d'un symbol
let symbol1 = Symbol();

//Utilisation d'un symbol comme propriété d'un objet
const MY_KEY = Symbol();
let obj = {
    [MY_KEY]: 123
};

Quelques liens sur le sujet :

Références

Quelques liens en complément de ceux de l’article précédent :

la suite au prochain épisode …