Beruflich Dokumente
Kultur Dokumente
sut.AddBook(1);
//?
}
}
Aber, ach, ohje… Wie prüft man denn nun, ob das hinzugefügte Buch auch im Warenkorb
angekommen ist? AddBook() ist ein Kommando und verändert den Zustand des Warenkorbs. Wie
kann man also ganz allgemein diesen Zustand in Tests prüfen?
sut.AddBook(1);
Assert.That(sut.Count, Is.EqualTo(1));
}
Mit einer Ableitung müssen Sie nicht einmal Design for Testability betreiben. Und die Flexibilität
wird auch nicht eingeschränkt. Eine scheinbar ideale Lösung, oder? Der Eingriff, private Variablen
auf protected statt private zu setzen, ist minimal. Und dass dieser Ansatz an abgeschlossenen
(sealed) Klassen scheitert, ist auch unbedeutend.
Dennoch will mir eine Ableitung vom eigentlichen SUT nicht recht schmecken. Nein, das liegt
nicht daran, dass ich Ableitungen für generell überbewertet halte. Hier wäre ja sogar das Liskov
Substitution Principle eingehalten. Den Aufwand für die Ableitungsklasse finde ich auch nicht zu
hoch.
Nein, es etwas anderes, das mich stört…
sut.AddBook(1);
Assert.That(books.Count, Is.EqualTo(1));
}
Das halte ich für genauso konsequent wie einfach zu verstehen. Etwas systematisiert lautet dann das
Muster:
1. Abhängigkeiten einer Klasse zusammenfassen in einer Abhängigkeitsklasse. Das gilt für
Zustände wie Funktionalität, von denen eine Klasse abhängt.
2. Während Tests die dafür minimal nötigen Abhängigkeiten mit einer Instanz der
Abhängigkeitsklasse injizieren.
3. Erwartungen an Zustandsänderungen nach Ausführung von Kommandos auf dem SUT
prüfen anhand der injizierten Abhängigkeitklasseninstanz.
sut.AddBook(1);
Assert.That(dependencies.books.Count, Is.EqualTo(1));
}
Diesem Verfahren steht auch die “normale” Dependency Injection nicht im Wege. Sie würde es
sogar verbergen. Dazu bräuchte die Abhängigkeitsklasse nur einen ausgewiesenen “Kanal” für die
Injektion der Funktionalität, von der der Warenkorb abhängig ist, z.B. so für Unity als DI
Container:
public class Dependencies
{
[Dependency]
public IPriceCalculator calc {get; set;}
public readonly Dictionary<int, int> books = …
}
Zusätzlich müsste im Mapping auch die Abhängigkeitsklasse aufgeführt werden. Aber das ist kein
sonderlicher Mehraufwand. Das ließe sich womöglich sogar automatisieren.