Ich möchte eine Klasse mithilfe der Abhängigkeitsinjektion testbar machen. Die Klasse erstellt jedoch zur Laufzeit mehrere Objekte und übergibt unterschiedliche Werte an ihren Konstruktor. Hier ist ein vereinfachtes Beispiel:
public abstract class Validator {
private ErrorList errors;
public abstract void validate();
public void addError(String text) {
errors.add(
new ValidationError(text));
}
public int getNumErrors() {
return errors.count()
}
}
public class AgeValidator extends Validator {
public void validate() {
addError("first name invalid");
addError("last name invalid");
}
}
(Es gibt viele andere Unterklassen von Validator.)
Wie kann ich dies am besten ändern, damit ich anstelle von ValidationError ein gefälschtes Objekt einfügen kann?
Ich kann eine AbstractValidationErrorFactory erstellen und stattdessen die Factory injizieren. Das würde funktionieren, aber es sieht so aus, als würde ich für jede Abhängigkeit dieser Art Tonnen kleiner Fabriken und Fabrikschnittstellen schaffen. Gibt es einen besseren Weg?
Antworten:
Die einfachste Änderung, um Ihre Klasseneinheit testbar zu machen, ist:
Das ist natürlich nicht sehr schön. Sie können die Klasse jedoch mit Komponententests abdecken. Anschließend können Sie mit der Umgestaltung des idealen Designs beginnen, ohne befürchten zu müssen, dass der Code durch tiefere Änderungen beschädigt wird.
Obligatorische Referenz: Effektiv mit Legacy Code arbeiten .
Über dieses ideale Design ist jedoch schwer viel zu sagen, da Ihrem Beispiel Details und Kontext fehlen. Wenn Sie uns mehr darüber erzählen, was Sie testen möchten und welche Rolle die getestete Klasse spielt, können wir Ihnen möglicherweise weiterhelfen.
quelle
Normalerweise ist die Lösung für dieses Problem das Anbietermuster:
Der Anbieter ähnelt der Fabrik. In diesem Fall wird bei
ValidationError
jedemget
Aufruf neu zurückgegeben.Weitere Informationen finden Sie im Buch Abhängigkeitsinjektion in Abschnitt 3.3.2 (Reinjektion mit dem Provider-Muster).
Guice hat zum Beispiel einen Anbieter dafür. Wenn Sie etwas Anspruchsvolleres wünschen, können Sie AssistedInject verwenden .
quelle