Tests en C# : Unit, Integration, E2E — niveau avancé

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

Introduction : Pourquoi écrire des tests à un niveau avancé ?

Le niveau débutant des tests en C# se limite généralement à des Assert.Equal simples et à des tests unitaires isolés. Cependant, dans les projets d'entreprise réels, cela ne suffit pas. Les bogues surviennent souvent à l'interface des composants — lors de l'interaction avec la base de données, des API externes ou dans une logique métier complexe avec des effets secondaires.

Les tests avancés en C# (.NET) consistent à savoir construire une pyramide de tests, où les tests unitaires sont rapides et isolés, les tests d'intégration vérifient les interactions réelles, et les tests E2E simulent le comportement de l'utilisateur. Dans cet article, nous examinerons les outils modernes : xUnit, Moq, FluentAssertions, Testcontainers et WebApplicationFactory. Vous apprendrez à écrire des tests fiables qui ne cassent pas lors du refactoring et qui donnent confiance dans le code.



1. Tests unitaires avancés : Objets Mock et Stub

Les tests unitaires doivent être isolés des dépendances externes. Au niveau avancé, nous utilisons des bibliothèques pour créer des objets mock, comme Moq ou NSubstitute.



Configuration correcte des objets Mock

Au lieu de créer des stubs manuellement, utilisez Mock.Of<T>() pour une configuration rapide. Exemple avec Moq et FluentAssertions :

public interface IEmailService{    Task SendAsync(string to, string subject);}

public class NotificationService{ private readonly IEmailService _emailService;

public NotificationService(IEmailService emailService) { _emailService = emailService; }

public async Task NotifyUserAsync(string email) { await _emailService.SendAsync(email, "Welcome!"); }}

// Test[Fact]public async Task NotifyUserAsync_ShouldSendEmail(){ // Arrange var mockEmailService = new Mock<IEmailService>(); var service = new NotificationService(mockEmailService.Object);

// Act await service.NotifyUserAsync("test@example.com");

// Assert mockEmailService.Verify( x => x.SendAsync("test@example.com", "Welcome!"), Times.Once);}


Évitez de tester les détails d'implémentation

L'approche avancée consiste à tester le comportement, et non les appels internes. Utilisez Verify uniquement pour les dépendances critiques. Pour les autres, vérifiez le résultat.



2. Tests d'intégration : Base de données et services externes

Les tests d'intégration vérifient que plusieurs modules fonctionnent ensemble. Pour .NET Core/5+, l'outil idéal est WebApplicationFactory (pour ASP.NET Core) et Testcontainers (pour la conteneurisation des dépendances).



Configuration de WebApplicationFactory avec une vraie base de données

Au lieu d'utiliser un fournisseur InMemory (qui se comporte différemment d'une vraie base de données), utilisez Testcontainers pour lancer PostgreSQL ou SQL Server dans Docker :

public class IntegrationTestFixture : IAsyncLifetime{    private readonly TestcontainersContainer _dbContainer;

public string ConnectionString { get; private set; }

public IntegrationTestFixture() { _dbContainer = new TestcontainersBuilder<TestcontainersContainer>() .WithImage("postgres:15") .WithPortBinding(5432, true) .WithEnvironment("POSTGRES_USER", "test") .WithEnvironment("POSTGRES_PASSWORD", "test") .WithEnvironment("POSTGRES_DB", "testdb") .Build(); }

public async Task InitializeAsync() { await _dbContainer.StartAsync(); ConnectionString = $"Host=localhost;Port={_dbContainer.GetMappedPublicPort(5432)};" + $"Database=testdb;Username=test;Password=test"; }

public async Task DisposeAsync() { await _dbConta

Blogs

Book Recommendations