Mein Motto für Java ist "nur weil Java statische Blöcke hat, bedeutet es nicht, dass Sie sie verwenden sollten." Witze beiseite, es gibt eine Menge Tricks in Java, die das Testen zu einem Albtraum machen. Zwei der meisten, die ich hasse, sind anonyme Klassen und statische Blöcke. Wir haben eine Menge Legacy-Code, der statische Blöcke verwendet, und diese sind einer der ärgerlichen Punkte in unseren Push-in-Unit-Tests. Unser Ziel ist es, Komponententests für Klassen schreiben zu können, die von dieser statischen Initialisierung mit minimalen Codeänderungen abhängig sind.Mocking statische Blöcke in Java
Bis jetzt ist mein Vorschlag zu meinen Kollegen, den Körper des statischen Blockes in eine private statische Methode zu bewegen und es staticInit
zu nennen. Diese Methode kann dann innerhalb des statischen Blocks aufgerufen werden. Beim Komponententest kann eine andere Klasse, die von dieser Klasse abhängt, leicht staticInit
mit JMockit überspielen, um nichts zu tun. Lass uns das im Beispiel sehen.
public class ClassWithStaticInit {
static {
System.out.println("static initializer.");
}
}
Wird
public class ClassWithStaticInit {
static {
staticInit();
}
private static void staticInit() {
System.out.println("static initialized.");
}
}
Damit wir in einem JUnit folgendes tun können, um
geändert werden.public class DependentClassTest {
public static class MockClassWithStaticInit {
public static void staticInit() {
}
}
@BeforeClass
public static void setUpBeforeClass() {
Mockit.redefineMethods(ClassWithStaticInit.class, MockClassWithStaticInit.class);
}
}
Allerdings hat diese Lösung auch ihre eigenen Probleme. Sie können DependentClassTest
und ClassWithStaticInitTest
nicht auf derselben JVM ausführen, da Sie den statischen Block tatsächlich für ClassWithStaticInitTest
ausführen möchten.
Was wäre Ihre Art, diese Aufgabe zu erfüllen? Oder irgendwelche besseren, nicht auf JMockit basierenden Lösungen, von denen Sie denken, dass sie sauberer arbeiten würden?
Sie können mit EasyMock nicht "statische" oder "private" Methoden vortäuschen. Das Bewegen des Körpers des statischen Initialisierers ist so weit von einem Refactoring, das wir für jetzt tun können. –
Wenn die zu testende Klasse die statische Methode init/private hat, soll sie aufgerufen werden. Kein Problem. Aber wenn es die Klasse ist, die verspottet wird, ist das kein Problem für leichtes Spott: Es wird nicht aufgerufen, weil es KEINE UMSETZUNG gibt. Sie können sich die öffentlichen Schnittstellen so anhören, als wären die privaten Daten nicht vorhanden. –