Objets mock et fixtures en C# : le secret du test unitaire parfait

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi vos tests mentent-ils et comment y remédier ?

\n\n

Imaginez : vous écrivez un code parfait en C#, vous le couvrez de tests, le voyant vert s'allume, le pipeline CI est heureux. Vous publiez la version… et la production plante. Cela vous dit quelque chose ? Le problème ne vient probablement pas du code, mais des tests. Ils ne testaient pas votre vrai code, mais sa version « jouet », liée à la base de données, au système de fichiers ou à une API externe.

\n\n

Bienvenue dans le monde des objets mock et des fixtures — les deux piliers sur lesquels repose un test unitaire de qualité en C#. Sans eux, vos tests ne sont que de fragiles vérifications d'intégration qui se brisent au moindre changement d'environnement. Avec eux, vous obtenez des tests rapides, isolés et fiables qui protègent réellement votre code.

\n\n

Dans cet article, nous allons voir : en quoi un mock diffère d'un stub et d'un fake, comment configurer correctement les fixtures, et nous montrerons des exemples concrets avec les bibliothèques populaires : Moq, NSubstitute et AutoFixture. C'est parti !

\n\n

Mock, Stub, Fake — quelle est la différence ? (Indice : c'est important)

\n\n

Avant d'écrire du code, mettons-nous d'accord sur les termes. De nombreux développeurs utilisent le mot « mock » pour tout et n'importe quoi, mais cela mène à la confusion. Dans la classification de Gerard Meszaros (livre « xUnit Test Patterns »), il existe une distinction claire :

\n\n
    \n
  • Dummy — un objet qui est passé mais jamais utilisé. Il sert uniquement à remplir les paramètres.
  • \n
  • Stub — fournit des réponses préparées à l'avance aux appels. Vous vérifiez l'état (state verification).
  • \n
  • Fake — une implémentation fonctionnelle mais simplifiée (par exemple, InMemoryRepository au lieu d'une vraie base de données).
  • \n
  • Mock — un objet qui vérifie le comportement (behavior verification). Vous affirmez qu'une méthode spécifique a été appelée avec des arguments spécifiques.
  • \n
\n\n

En pratique, en C#, nous utilisons le plus souvent des objets mock (via Moq ou NSubstitute) pour vérifier les interactions, et des fixtures (via AutoFixture) pour générer rapidement des données de test. Mais procédons dans l'ordre.

\n\n

Objets mock en C# : isoler les dépendances

\n\n

Imaginez que vous ayez un service OrderService qui, lors de la validation d'une commande, envoie un email et enregistre les données dans une base de données. Le tester « pour de vrai » signifie envoyer des emails et écrire dans la base à chaque fois. C'est lent, peu fiable et coûteux.

\n\n

La solution — l'isolation des dépendances. Nous remplaçons les objets réels (EmailSender, DbContext) par des objets mock et vérifions que le service appelle les bonnes méthodes avec les bons paramètres.

\n\n

Exemple avec Moq (la bibliothèque la plus populaire)

\n\n
public interface IEmailSender\n{\n    void Send(string to, string subject, string body);\n}\n\npublic interface IOrderRepository\n{\n    void Save(Order order);\n}\n\npublic class OrderService\n{\n    private readonly IEmailSender _emailSender;\n    private readonly IOrderRepository _repository;\n\n    public OrderService(IEmailSender emailSender, IOrderRepository repository)\n    {\n        _emailSender = emailSender;\n        _repository = repository;\n    }\n\n    public void PlaceOrder(Order order)\n    {\n        // Logique métier\n        _repository.Save(order);\n        _emailSender.Send(order.CustomerEmail, "Commande confirmée", $"Votre commande #{order.Id} a été validée.");\n    }\n}
\n\n

Écrivons maintenant un test en utilisant Moq :

\n\n
[TestFixture]\npublic class OrderServiceTests\n{\n    [Test]\n    public void PlaceOrder_ShouldSendEmail_WhenOrderIsValid()\n    {\n        // Arrange\n        var mockEmailSender = new Mock<IEmailSender>();\n        var mockRepository = new Mock<IOrderRepository>();\n        var service = new OrderService(mockEmailSender.Object, mockRepository.Object);\n        var order = new Order { Id =                

Blogs

Book Recommendations