Ich habe ein interessantes JUnit Problem hier (JUnit 4.12). Ich habe eine Basisklasse , die nur statische Methoden hat. Sie müssen statisch sein, wegen der Art , wie sie es gewohnt sind. Ich erben andere Klassen von der Basisklasse. Also, wenn die Basisklasse ist Base
, haben wir ChildA
und ChildB
.
Die meisten Methoden sind in der Basisklasse enthalten, aber es hat zu wissen, welches Kind es ist eigentlich (Aufruf nur die Methoden, wie die Basisklasse ist ungültig). Dies geschieht über ein statisches Datenelement in der Basisklasse getan:
public class Base {
protected static ChildType myType = ChildType.Invalid;
...
}
Jedes Kind legt das Datenelement über einen statischen Initialisierer, also:
static {
myType = ChildType.ChildA;
}
Dann, wenn die Methoden aufgerufen werden, weiß die Basisklasse, welche Art es ist, und lädt die entsprechenden Konfigurationen (die Art ist eigentlich ein Konfigurationsname).
Das alles funktioniert perfekt, wenn die Anwendung ausgeführt wird. Stepping durch sie im Debugger und durch Log-Meldungen, kann ich die entsprechenden Arten festgelegt und die Methoden laden die entsprechenden Konfigurationen auf der Grundlage des Kindes Art sehen.
Das Problem entsteht, wenn JUnit verwenden. Wir haben einige JUnit-Tests jeder der Basisklasse Methoden zu testen. Da nur auf die Basisklasse die Methoden aufrufen ungültig ist, rufen wir die Methoden für die untergeordneten Klassen, also:
bool result = ChildA.methodTwo();
Diese ‚‘ nicht immer ‚‘. Warum? Die statische Initialisierer wird nie genannt. Wenn Sie den Code als eine Anwendung ausgeführt wird, wird es genannt, und jeder ist glücklich. Wenn ich es als JUnit Test ausführen, ist der statische Initialisierer übersprungenen und die Methoden haben ungültige Daten. Was ist JUnit tun, dass die statische Initialisierer überspringt? Gibt es eine Möglichkeit, um es?
Einzelheiten
In Wirklichkeit sind rufen wir nicht die Methode, wie ich oben geschrieben. Ich wollte nur das Beispiel so klar wie möglich sein. In Wirklichkeit haben wir einen Web Service mit dem Jersey Rahmen geschrieben. Die Methode aufgerufen wird, eine der REST-Endpunkte.
@POST
@Produces(MediaType.TEXT_PLAIN)
public String methodPost() {
...
return new String( itWorked ? "success" : "fail" );
}
Und wir nennen es so (sorry über die hässliche Syntax, es ist nur so, wie es funktioniert):
@Test
public void testThePost() throws Exception {
javax.ws.rs.core.Response response = target("restapi/").request().post(Entity.entity(null, MediaType.TEXT_PLAIN));
assertEquals( 200, response.getStatus() );
}
Alle GET Tests Arbeit und die statische Initialisierer auf alle von ihnen genannt wird. Es ist nur diese POST, die fehlschlägt, und nur beim Ausführen des JUnit-Tests.
Ich beschloss, zu versuchen, was @Arkdiy vorgeschlagen und haben Passthrough-Methoden in den Kinderklassen.
Lassen Sie mich wiederholen: der Code, wie ich es hatte, perfekt funktioniert , wenn als Anwendung ausführen. Erst wenn über JUnit läuft nicht versagt es .
So, jetzt habe ich etwas Ähnliches wie die folgende Liste:
public class BaseClass {
protected static ChildType myType = ChildType.Invalid;
...
public static boolean methodTwoBase() {
...
}
}
public class ChildA extends BaseClass {
public static boolean methodOne() {
...
}
public static boolean methodTwo() {
myType = ChildType.ChildA;
return methodTwoBase();
}
}
public class ChildB extends BaseClass {
public static boolean methodOne() {
...
}
public static boolean methodTwo() {
myType = ChildType.ChildB;
return methodTwoBase();
}
}
Da ich nicht statische Methoden außer Kraft setzen kann, muss die Version der Methode in der Basisklasse eine andere Signatur ( methodTwoBase()
statt methodTwo
). Ich habe versucht , es als eine regelmäßige Anwendung und in JUnit und es funktioniert in beiden Richtungen.
Art ein interessantes Problem, und ich Schuld JUnit. Vielen Dank für den Input!
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen