Wie kann ich mit JUnit eine Klasse testen, die interne private Methoden, Felder oder verschachtelte Klassen hat?
Es scheint schlecht, den Zugriffsmodifikator für eine Methode zu ändern, nur um einen Test durchführen zu können.
Wie kann ich mit JUnit eine Klasse testen, die interne private Methoden, Felder oder verschachtelte Klassen hat?
Es scheint schlecht, den Zugriffsmodifikator für eine Methode zu ändern, nur um einen Test durchführen zu können.
Das ist IMO die beste Antwort, oder wie es gewöhnlich heißt: Testen Sie das Verhalten, nicht die Methoden. Unit-Tests sind kein Ersatz für Quellcode-Metriken, statische Code-Analyse-Tools und Code-Reviews. Wenn private Methoden so komplex sind, dass sie separate Tests benötigen, dann müssen sie wahrscheinlich umstrukturiert werden, und nicht mit mehr Tests überhäuft werden.
Schreiben Sie also keine privaten Methoden, sondern erstellen Sie einfach 10 weitere kleine Klassen?
Nein, es bedeutet im Grunde, dass Sie die Funktionalität der privaten Methoden mit der öffentlichen Methode testen können, die sie aufruft.
Dies sind nur zwei Beispiele dafür, wo ich eine private Methode testen möchte:
SecurityManager
nicht so konfiguriert ist, dass dies verhindert wird).Ich verstehe die Idee, nur den "Vertrag" zu testen. Aber ich sehe nicht, dass man dafür plädieren kann, den Code tatsächlich nicht zu testen - je nachdem, wie man es sieht.
Mein Kompromiss besteht also darin, die JUnits mit Reflection zu verkomplizieren, anstatt meine Sicherheit und mein SDK zu gefährden.
Sie sollten eine Methode niemals öffentlich machen, nur um sie zu testen, private
ist nicht die einzige Alternative. Kein Zugangsmodifikator ist package private
und bedeutet, dass Sie einen Unit-Test durchführen können, solange sich Ihr Unit-Test im selben Paket befindet.
@ngreen das ist alles wahr, aber darum geht es in der Frage nicht. OP fragt nach dem Testen privater Methoden. Standard ist nicht dasselbe wie privat; wie bereits erwähnt, kann man eine Standardzugriffsmethode einer Klasse leicht erkennen, indem man die Klasse einfach im selben Paket deklariert. Bei privatem Zugriff ist Reflexion erforderlich, was eine ganz andere Sache ist.
Ich habe mich zu Ihrer Antwort, insbesondere zu Punkt 1, geäußert, nicht zum OP. Es gibt keinen Grund, eine Methode privat zu machen, nur weil Sie nicht wollen, dass sie öffentlich ist.
Die privaten Methoden werden von einer öffentlichen Methode aufgerufen, so dass die Eingaben zu Ihren öffentlichen Methoden auch private Methoden testen sollten, die von diesen öffentlichen Methoden aufgerufen werden. Wenn eine öffentliche Methode fehlschlägt, dann könnte das ein Fehler in der privaten Methode sein.
Wahre Tatsache. Das Problem ist, wenn die Implementierung komplizierter ist, z. B. wenn eine öffentliche Methode mehrere private Methoden aufruft. Welche davon ist fehlgeschlagen? Oder wenn es sich um eine komplizierte private Methode handelt, die weder offengelegt noch in eine neue Klasse übertragen werden kann.
In der Spring Framework können Sie private Methoden mit dieser Methode testen:
ReflectionTestUtils.invokeMethod()
Zum Beispiel:
ReflectionTestUtils.invokeMethod(TestClazz, "createTest", "input data");
Ein anderer Ansatz, den ich verwendet habe, besteht darin, eine private Methode in package private oder protected zu ändern und sie dann mit der @VisibleForTesting Anmerkung der Google Guava-Bibliothek.
Dies zeigt jedem, der diese Methode verwendet, dass er vorsichtig sein muss und nicht direkt darauf zugreifen darf, auch nicht in einem Paket. Auch eine Testklasse muss sich nicht im selben Paket befinden physisch sondern im selben Paket unter dem Namen Test Ordner.
Wenn zum Beispiel eine zu prüfende Methode in src/main/java/mypackage/MyClass.java
dann sollte Ihr Testaufruf in src/test/java/mypackage/MyClassTest.java
. Auf diese Weise haben Sie Zugriff auf die Testmethode in Ihrer Testklasse.
Ich wusste nichts davon, es ist interessant, aber ich denke immer noch, dass man Designprobleme hat, wenn man diese Art von Annottaion braucht.
Für mich ist das so, als würde man, anstatt dem Brandschutzbeauftragten einen einmaligen Schlüssel zu geben, um die Brandschutzübung zu testen, die Haustür unverschlossen lassen und ein Schild an der Tür anbringen, auf dem steht: "Unverschlossen für Testzwecke - wenn Sie nicht von unserem Unternehmen sind, bitte nicht eintreten".
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
327 Stimmen
Der beste Weg, eine private Methode zu testen, ist, sie nicht direkt zu testen
30 Stimmen
Lesen Sie den Artikel Testen privater Methoden mit JUnit und SuiteRunner .
3 Stimmen
Warum sollte eine private Funktion getestet werden? Sie wird ohnehin automatisch getestet (und muss getestet werden), wenn Sie die Funktion/Methode testen, die die private Funktion verwendet.
7 Stimmen
Ich habe diese Frage in ihren ursprünglichen Zustand zurückversetzt, bevor ich die Frage generiert habe. In ihrem jetzigen Zustand sind die Antworten sehr Java-orientiert, und die Frage konzentrierte sich weitgehend auf das "Wie", was bedeutet, dass die späteren Versionen, die Java auslöschen und für andere Sprachen verallgemeinern, und am Ende den Fokus auf C++ verlagern, viel zu viele der Antworten ungültig machen. Eine verallgemeinerte Form, die nach dem "Wie" in einer beliebigen Sprache und einem beliebigen Framework fragt, würde ebenfalls als viel zu weit gefasst angesehen werden, was bedeutet, dass die letzten Bearbeitungen diese Frage eher in Richtung Schließung als in Richtung Konstruktivität getrieben haben.
8 Stimmen
@AkashVerma: Aus demselben Grund, aus dem Sie Unit-Tests statt nur Systemtests durchführen wollen?
0 Stimmen
Siehe auch: stackoverflow.com/questions/250692/ . Die zugrunde liegende philosophische Frage ist sprachunabhängig.
0 Stimmen
Siehe: github.com/ljr1981/stack_overflow_answers/blob/main/src/ y github.com/ljr1981/stack_overflow_answers/blob/main/testing/
0 Stimmen
Im vorherigen Kommentar zeige ich Ihnen, wie einfach das in Eiffel ist. In diesem Fall habe ich eine Klasse namens SO_34571 mit einem Methoden-Feature namens `my_private_method' erstellt. Beachten Sie, dass auf das Gruppenschlüsselwort "feature" ein {TEST_SET_BRIDGE} folgt. Das bedeutet, dass jede Klasse, die von TEST_SET_BRIDGE erbt (einschließlich ihrer Nachkommen), die Erlaubnis hat, auf jedes Feature der Feature-Gruppe zuzugreifen. Sauber. Einfach. Elegant. Skalierbar. Kontrollierbar. Schön!