So testen Sie private Methoden in Java und Kotlin

GOVIND DIXIT
GOVIND DIXIT

Folgen Sie

Jul 23, 2019 · 4 Minuten Lesezeit

Ja, das ist die Millionen-Dollar-Frage. Wie Unit-Test private Methoden?

Sollte ein Entwickler die privaten Methoden in seiner Codebasis testen? oder sie dem Vertrauen der Öffentlichkeit zu überlassen, ist ein Weg. Jeder Entwickler hat seine eigene Meinung, ob wir sie tatsächlich testen sollen oder nicht. Kurz gesagt, die Frage wurde auf „Gibt es einen guten Ansatz, den wir für diesen Job ausprobieren können?“

Hier sind also alle möglichen Optionen, die einem Entwickler zur Verfügung stehen, um private Methoden seiner Java / Kotlin-basierten Apps im Jahr 2019 zu testen:

  1. Teste keine privaten Methoden 😜(Keine Wurzeln, keine sauren Trauben)
  2. Gib den Methoden öffentlichen Zugang 😒 (Nein, ich werde das nicht tun, es ist gegen Codierungspraktiken. Ich bin ein guter Entwickler, ich folge Best Practices)
  3. Verwenden Sie eine verschachtelte Testklasse 😒 (Dies ist nicht gut für gemischten Produktionscode mit Testcode. Muss ich noch einmal erwähnen, dass ich ein guter Entwickler bin und nur Best Practices befolge?
  4. Verwenden Sie Java Reflection 😃(Ja, das scheint interessant, ich bin dafür)

Trotz der allgemeinen Überzeugung ist es tatsächlich möglich, über Java Reflection auf private Felder und Methoden anderer Klassen zuzugreifen. Es ist nicht einmal so schwierig. Dies kann während des Komponententests sehr praktisch sein.Hinweis: Dies funktioniert nur, wenn Sie den Code als eigenständige Java-Anwendung ausführen, wie Sie es bei Komponententests und regulären Anwendungen tun. Wenn Sie versuchen, dies in einem Java-Applet zu tun, müssen Sie mit dem SecurityManager herumspielen. Da Sie dies jedoch nicht sehr oft tun müssen, wird es in diesem Text bisher weggelassen.

Methodenparameter-Reflektionsunterstützung wurde in Java 8 hinzugefügt. Einfach ausgedrückt, bietet es Unterstützung für das Abrufen der Namen von Parametern zur Laufzeit.

Um auf ein privates Feld zuzugreifen, müssen Sie die Class.getDeclaredField(String name) oder Class.getDeclaredFields() Methode aufrufen. Die Methoden Class.getField(String name) und Class.getFields() geben nur öffentliche Felder zurück, funktionieren also nicht. Hier ist ein einfaches Beispiel für eine Klasse mit einem privaten Feld und darunter der Code für den Zugriff auf dieses Feld über Java Reflection:

public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}
}PrivateObject privateObject = new PrivateObject("The Private Value");Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");privateStringField.setAccessible(true);String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);

Dieses Codebeispiel gibt den Text "fieldValue = The Private Value” aus, der der Wert des privaten Felds privateString des PrivateObject die Instanz, die am Anfang des Codebeispiels erstellt wurde.

Beachten Sie die Verwendung der Methode PrivateObject.class.getDeclaredField("privateString"). Es ist dieser Methodenaufruf, der das private Feld zurückgibt. Diese Methode gibt nur Felder zurück, die in dieser bestimmten Klasse deklariert sind, keine Felder, die in einer Superklasse deklariert sind.

Beachten Sie auch die fettgedruckte Zeile. Durch Aufrufen von Field.setAcessible(true) deaktivieren Sie die Zugriffsprüfungen für diese spezielle Field Instanz nur zur Reflektion. Jetzt können Sie darauf zugreifen, auch wenn es sich um einen privaten, geschützten oder Paketbereich handelt, auch wenn der Aufrufer nicht Teil dieser Bereiche ist. Sie können immer noch nicht mit dem normalen Code auf das Feld zugreifen. Der Compiler wird es nicht zulassen.

Zugriff auf private Methoden

Um auf eine private Methode zuzugreifen, müssen Sie die Class.getDeclaredMethod(String name, Class parameterTypes) oder Class.getDeclaredMethods() Methode aufrufen. Die Methoden Class.getMethod(String name, Class parameterTypes) und Class.getMethods() geben nur öffentliche Methoden zurück, sodass sie nicht funktionieren.

Hier ist ein einfaches Beispiel einer Klasse mit einer privaten Methode und darunter der Code, um über Java Reflection auf diese Methode zuzugreifen:

public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}private String getPrivateString(){
return this.privateString;
}
}PrivateObject privateObject = new PrivateObject("The Private Value");Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);privateStringMethod.setAccessible(true);String returnValue = (String)
privateStringMethod.invoke(privateObject, null);System.out.println("returnValue = " + returnValue);

Dieses Codebeispiel gibt den Text "returnValue = The Private Value” aus, der der Wert ist, der von der Methode getPrivateString() zurückgegeben wird, wenn sie auf der PrivateObject der Instanz aufgerufen wird, die zu Beginn des Codebeispiels erstellt wurde.

Beachten Sie die Verwendung der Methode PrivateObject.class.getDeclaredMethod("privateString"). Es ist dieser Methodenaufruf, der die private Methode zurückgibt. Diese Methode gibt nur Methoden zurück, die in dieser bestimmten Klasse deklariert sind, keine Methoden, die in Superklassen deklariert sind.

Beachten Sie auch die fettgedruckte Zeile. Durch Aufrufen von Method.setAcessible(true) deaktivieren Sie die Zugriffsprüfungen für diese spezielle Method Instanz nur zur Reflektion. Jetzt können Sie darauf zugreifen, auch wenn es sich um einen privaten, geschützten oder Paketbereich handelt, auch wenn der Aufrufer nicht Teil dieser Bereiche ist. Sie können immer noch nicht mit dem normalen Code auf die Methode zugreifen. Der Compiler wird es nicht zulassen.

Versuchen wir dieses Wissen mit einem Code auf Produktionsebene.
Hier ist die Klasse, die einige private Methoden enthält, die wir testen möchten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.