Webframeworkk/ASP.NET Core/Erweiterter Unit-Test
Dieses Tutorial bietet einen umfassenden Überblick über moderne Tools und Techniken für Unit- und Integrationstests in der .NET-Entwicklung. Wir konzentrieren uns auf Fluent Assertions, AutoFixture, Mocking mit Moq und Integrationstests.
1. Fluent Assertions
Fluent Assertions ist eine Bibliothek, die Unit-Tests durch eine natürlichere, flüssige Syntax lesbarer macht.
Vorteile
- Lesbarkeit: Tests lesen sich wie normales Englisch.
- Wartbarkeit: Klare Fehlermeldungen erleichtern die Fehlersuche.
- Umfangreiches API: Deckt Collections, Strings, Exceptions und mehr ab.
Beispiele
// Einfache Assertions
result.Should().Be(5);
result.Should().NotBeNull();
// String Assertions
name.Should().StartWith("John").And.EndWith("Doe");
// Collection Assertions
list.Should().HaveCount(3).And.Contain("apple");
// Exception Assertions
Action act = () => someMethod();
act.Should().Throw<ArgumentException>().WithMessage("Invalid operation");
2. AutoFixture
AutoFixture automatisiert die Erstellung von Testdaten, was besonders bei komplexen Objekten mit vielen Abhängigkeiten wertvoll ist.
Integration mit xUnit
Installieren Sie das Paket AutoFixture.Xunit2 und nutzen Sie das [AutoData] Attribut:
[Theory, AutoData]
public void CreatePerson_ValidPerson_ReturnsOk(Person person, Mock<IPersonsService> mockPersonsService)
{
// AutoFixture erstellt automatisch eine Instanz von Person
// ... Testlogik
}
Vorteile
- Reduzierung von Boilerplate-Code.
- Einfache Anpassung generierter Daten.
- Fokus auf die eigentliche Testlogik statt auf Daten-Setup.
3. Mocking mit Moq
Mocking ermöglicht es, eine Code-Einheit (Unit) isoliert von ihren Abhängigkeiten (z.B. Datenbanken oder APIs) zu testen.
Funktionsweise
- Mock erstellen:
var mockRepo = new Mock(); - Verhalten festlegen:
mockRepo.Setup(r => r.GetAll()).ReturnsAsync(new List()); - Mock injizieren: Den Mock an den Konstruktor der zu testenden Klasse übergeben.
- Interaktionen verifizieren:
mockRepo.Verify(r => r.GetAll(), Times.Once());
Best Practices beim Mocking
- Bedarfsorientiert: Nur das mocken, was für den Test notwendig ist.
- Verhalten statt Details: Testen Sie, was passiert, nicht wie es implementiert ist.
4. Integrationstests
Integrationstests prüfen das Zusammenspiel verschiedener Komponenten (Controller, Services, Datenbank).
Key Elements
- WebApplicationFactory: Simuliert den Webserver im Test.
- HttpClient: Sendet HTTP-Requests an den Testserver.
- In-Memory Database: Ermöglicht schnelle Datenbanktests ohne externe Abhängigkeiten.
Beispiel: CustomWebApplicationFactory
public class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Test");
builder.ConfigureServices(services => {
// DB-Kontext durch In-Memory Datenbank ersetzen
services.AddDbContext<ApplicationDbContext>(options => {
options.UseInMemoryDatabase("TestDb");
});
});
}
}
5. Best Practices für Unit Tests
Um effektive Tests zu schreiben, sollten diese folgende Kriterien erfüllen:
- Isoliert: Keine Abhängigkeit von Dateisystem oder echten Datenbanken.
- Schnell: Ausführung in wenigen Millisekunden.
- Wiederholbar: Gleiches Ergebnis bei jedem Durchlauf.
- Eindeutig: Nur eine Methode pro Testfall prüfen.
Interview-Tipps
- Erklären Sie den Unterschied zwischen Fakes (Dummy-Implementierung) und Mocks (vordefinierte Rückgabewerte).
- Kennen Sie die Vorteile von
[Theory]gegenüber[Fact]in xUnit. - Betonen Sie die Wichtigkeit der Test-Isolierung.