Testen in C#: Unit, Integration, E2E — Vollständiger Leitfaden für .NET

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten
Here is the translated HTML content in German, with all tags preserved and only the text content translated. ```html

Testen in C#: Von Unit bis E2E – Wie man eine qualitativ hochwertige Testarchitektur in .NET aufbaut



Die Softwarequalität hängt direkt vom Testsystem ab. Im Ökosystem von C# und .NET gibt es eine etablierte Testpyramide: Modultests (Unit), Integrationstests (Integration) und End-to-End-Tests (E2E). In diesem Artikel werden wir jede Ebene anhand praktischer Beispiele durchgehen, zeigen, welche Bibliotheken verwendet werden, und fertige Codevorlagen bereitstellen.



1. Unit-Testing: Die Grundlage für Code-Stabilität



Unit-Tests überprüfen die Funktionsweise einzelner Methoden, Klassen oder Komponenten isoliert von externen Abhängigkeiten (DB, API, Dateisystem). Das Hauptziel ist es, Regressionen bei Refactoring schnell zu finden.



Werkzeuge für C#

  • NUnit – Klassisches Framework mit Attributen wie [Test], [TestCase].
  • xUnit – Modernes Framework von den Erstellern von NUnit, bevorzugt in neuen Projekten.
  • Moq – Bibliothek zum Erstellen von Mock-Objekten.
  • FluentAssertions – Für lesbare Asserts.


Beispiel eines Unit-Tests mit xUnit und Moq

Angenommen, wir haben einen Rabattberechnungsdienst, der auf ein Benutzer-Repository zugreift:



public interface IUserRepository{    bool IsPremiumUser(int userId);}

public class DiscountService{ private readonly IUserRepository _userRepo; public DiscountService(IUserRepository userRepo) => _userRepo = userRepo;

public decimal CalculateDiscount(int userId, decimal amount) { if (_userRepo.IsPremiumUser(userId)) return amount * 0.9m; // 10% Rabatt return amount; }}

// Testpublic class DiscountServiceTests{ [Fact] public void CalculateDiscount_ForPremiumUser_Returns90Percent() { // Arrange var mockRepo = new Mock<IUserRepository>(); mockRepo.Setup(r => r.IsPremiumUser(It.IsAny<int>())).Returns(true); var service = new DiscountService(mockRepo.Object);

// Act var result = service.CalculateDiscount(1, 100m);

// Assert Assert.Equal(90m, result); }}


Tipp: Verwenden Sie [Theory] und [InlineData] in xUnit für parametrisierte Tests – das reduziert Code-Duplizierung.



2. Integrationstests: Überprüfung der Komponentenverknüpfung



Integrationstests prüfen, wie Ihre Module mit echten externen Systemen interagieren: Datenbanken, Warteschlangen, Webservices. Im Gegensatz zu Unit-Tests werden hier keine Mocks verwendet – wir starten echte Umgebungen.



Bibliotheken und Ansätze

  • TestContainers – Startet Docker-Container (PostgreSQL, SQL Server, Redis) direkt aus den Tests.
  • WebApplicationFactory (aus Microsoft.AspNetCore.Mvc.Testing) – Erstellt einen Test-Host für ASP.NET Core.
  • Respawn – Bereinigt die Datenbank zwischen Tests, ohne den Container neu zu erstellen.


Beispiel eines Integrationstests mit TestContainers und WebApplicationFactory

Wir überprüfen, ob unsere API einen Benutzer korrekt in PostgreSQL speichert:



public class UserApiIntegrationTests : IClassFixture<TestContainersFixture>{    private readonly HttpClient _client;    private readonly TestContainersFixture _fixture;

public UserApiIntegrationTests(TestContainersFixture fixture) { _fixture = fixture; var factory = new WebApplicationFactory<Program>() .WithWebHostBuilder(builder => { builder.ConfigureTestServices(services => { // Ersetzen der echten Verbindungszeichenfolge durch den Container services.RemoveAll<DbContextOptions<AppDbContext>>(); se ```

Blogs

Buchempfehlungen