Blog

JUnit 4.7 @Regeln!!!

Wilfred Springer

Wilfred Springer

Aktualisiert Oktober 23, 2025
3 Minuten

Ich habe eine Weile gebraucht, bis ich wirklich verstanden habe, was es mit dieser @Rule in JUnit 4.7 auf sich hat, aber sie gefällt mir!

Letzte Woche musste ich sicherstellen, dass ich einen RESTful Web Service Client testen kann. Ich wollte eigentlich nur sicherstellen, dass ein Webserver immer eine bestimmte Antwort zurückgibt. Da der Test jedoch auf einem Continuous Integration Server ausgeführt werden sollte, bestand - wie immer - die Gefahr von Portkonflikten.
Das habe ich also getan:

Erstellen eines Webservers

Nun, nicht wirklich ein vollständiger Webserver, sondern eher ein Wrapper um Jetty herum, der WebServer genannt wird. Dieser WebServer implementierte jedoch MethodRule. Und das ist der Trick. Wenn Sie in Ihrer Testklasse ein Feld erstellen, das auf ein Objekt verweist, das die MethodRule-Schnittstelle implementiert, und dieses durch Hinzufügen der @Rule-Implementierung für die Verarbeitung als Regel markieren, ruft JUnit Ihre Instanz für jeden ausgeführten Test auf und ermöglicht es Ihnen, zusätzliches Verhalten für Ihre Testausführung hinzuzufügen.

[java] interface MethodRule { Statement apply(final Statement base, FrameworkMethod method, Object target) } [/java]

Meine WebServer-Klasse implementiert diese Methode, indem sie Jetty startet und stoppt. So steht es in meiner Testklasse:

[java] @Rule public WebServer server = new WebServer("WEBSERVER_PORT", 9191); [/java]

Beachten Sie, dass mein WebServer-Konstruktor zwei Parameter enthält. Der erste Parameter enthält den Namen einer Umgebungsvariablen, die möglicherweise existiert. Wenn sie vorhanden ist, wird der Wert dieser Umgebungsvariablen als Portnummer für den Webserver verwendet. Der zweite Parameter ist die Standard-Portnummer, die verwendet wird, wenn die Portnummer nicht durch die Umgebungsvariable festgelegt ist.

Umgebungsvariablen?

Der Grund für die Möglichkeit, hier eine Umgebungsvariable zu übergeben, ist, dass Hudson so sicherstellen kann, dass es keine Portkonflikte gibt. Natürlich weiß ich bei all dem nicht im Voraus, welche Portnummer verwendet werden wird. Deshalb implementiert mein Webserver auch eine Methode getURL(), die eine String-Darstellung der Ressource zurückgibt, auf die wir zugreifen werden. Ich muss mir die Portnummer nicht merken. Der WebServer teilt mir einfach mit, welchen Port er verwendet.

Welche Ressource?

Jetzt höre ich schon die nächste Frage: Woher soll der WebServer wissen, welche Ressource er serverisieren muss? Das ist eine gute Frage. Wenn das alles funktioniert, ist es besser, wenn Sie sich in Ihrem Test nicht darum kümmern müssen. (Ich meine, Sie könnten den WebServer natürlich von Ihrem Test aus weiter konfigurieren, aber das wäre etwas umständlich, da er ja bereits läuft.)

Anmerkungen zur Rettung

Die Antwort ist einfacher, als Sie vielleicht erwarten: Sie verwenden einfach eine andere Anmerkung. Das ist zwar nicht etwas, was @Rule vorschreibt, aber ich habe das Gefühl, dass sich dieses Muster durchsetzen wird. Im Grunde genommen teile ich dem WebServer mit, welche Ressource er bereitstellen soll, indem ich eine Anmerkung zu meiner Testmethode anbringe.
Mein Test sieht also folgendermaßen aus:

[java] @Test @WebResource(content="classpath:whatever.xml", contentType="text/xml") public void shouldBeAbleToDealWithWhatever { String url = server.getURL(); // Laden Sie mit Ihrem Client etwas von dieser URL herunter } [/java]

Beachten Sie das Präfix classpath: hier. Dies ist eine kleine Anleihe bei Spring. Damit wird der WebServer gezwungen, die Ressource auf dem Klassenpfad zu suchen. Wenn Sie Ihre Tests von Maven aus ausführen, ist dies eine hervorragende Möglichkeit, dem WebServer mitzuteilen, dass er in src/test/resources suchen soll.

Schlussfolgerungen

@Regel regiert. Das funktioniert wunderbar. Und die Verwendung von Anmerkungen zu Ihren Testmethoden, um die Ausführung Ihrer Regeln zu parametrisieren, macht sie sogar noch nützlicher. (Der Quellcode wurde hier hochgeladen: junit-webtest-rule/.)

Verfasst von

Wilfred Springer

Contact

Let’s discuss how we can support your journey.