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.
Auf eine private Methode darf nur innerhalb der gleichen Klasse zugegriffen werden. Es gibt also keine Möglichkeit, eine "private" Methode einer Zielklasse von einer beliebigen Testklasse aus zu testen. Ein Ausweg ist die manuelle Durchführung von Einheitstests oder die Änderung der Methode von "privat" in "geschützt".
Und dann kann auf eine geschützte Methode nur innerhalb desselben Pakets zugegriffen werden, in dem die Klasse definiert ist. Wenn Sie also eine geschützte Methode einer Zielklasse testen wollen, müssen Sie Ihre Testklasse im selben Paket wie die Zielklasse definieren.
Wenn die oben genannten Punkte nicht Ihren Anforderungen entsprechen, verwenden Sie der Weg der Reflexion um auf die private Methode zuzugreifen.
Sie verwechseln "geschützt" mit "freundlich". Auf eine geschützte Methode kann nur von einer Klasse zugegriffen werden, deren Objekte der Zielklasse zugeordnet werden können (d.h. Unterklassen).
Eigentlich gibt es in Java keinen "Friendly", der Begriff lautet "Package" und wird durch das Fehlen des Modifikators "private/public/protected" angezeigt. Ich hätte diese Antwort einfach korrigiert, aber es gibt eine wirklich gute Antwort, die dies bereits sagt - ich würde also empfehlen, sie zu löschen.
Heute habe ich eine Java-Bibliothek zum Testen privater Methoden und Felder entwickelt. Sie wurde mit Blick auf Android entwickelt, kann aber wirklich für jedes Java-Projekt verwendet werden.
Wenn Sie einen Code mit privaten Methoden, Feldern oder Konstruktoren haben, können Sie BoundBox . Es tut genau das, wonach Sie suchen. Im Folgenden finden Sie ein Beispiel für einen Test, der auf zwei private Felder einer Android-Aktivität zugreift, um diese zu testen:
@UiThreadTest
public void testCompute() {
// Given
boundBoxOfMainActivity = new BoundBoxOfMainActivity(getActivity());
// When
boundBoxOfMainActivity.boundBox_getButtonMain().performClick();
// Then
assertEquals("42", boundBoxOfMainActivity.boundBox_getTextViewMain().getText());
}
BoundBox macht es einfach, private/geschützte Felder, Methoden und Konstruktoren zu testen. Sie können sogar auf Dinge zugreifen, die durch Vererbung verborgen sind. BoundBox bricht in der Tat die Kapselung auf. Sie ermöglicht Ihnen den Zugriff auf all diese Dinge durch Reflection, BUT alles wird zur Kompilierungszeit geprüft.
Es ist ideal für das Testen von Legacy-Code. Verwenden Sie es vorsichtig ;)
Zunächst möchte ich diese Frage stellen: Warum müssen Ihre privaten Mitglieder isoliert getestet werden? Sind sie so komplex und bieten so komplizierte Verhaltensweisen, dass sie unabhängig von der öffentlichen Oberfläche getestet werden müssen? Es handelt sich um Unit-Tests, nicht um "Line-of-Code"-Tests. Kümmern Sie sich nicht um den Kleinkram.
Wenn sie so groß sind, groß genug, dass diese privaten Mitglieder jeweils eine "Einheit" groß in der Komplexität - erwägen Refactoring solche privaten Mitglieder aus dieser Klasse.
Wenn Refactoring unangemessen oder undurchführbar ist, können Sie das Strategiemuster verwenden, um den Zugriff auf diese privaten Mitgliedsfunktionen/Mitgliedsklassen im Rahmen von Unit-Tests zu ersetzen? Im Rahmen von Unit-Tests würde die Strategie eine zusätzliche Validierung bieten, aber in Release-Builds wäre es ein einfaches Pass-Through.
Denn oft wird ein bestimmtes Codestück aus einer öffentlichen Methode in eine interne private Methode umgewandelt und ist dann der kritische Teil der Logik, den Sie möglicherweise falsch verstanden haben. Sie möchten dies unabhängig von der öffentlichen Methode testen
Selbst der kürzeste Code ist manchmal ohne Unit-Test nicht korrekt. Versuchen Sie einfach, die Differenz zwischen 2 geografischen Winkeln zu berechnen. 4 Zeilen Code, und die meisten werden es nicht beim ersten Versuch richtig machen. Solche Methoden brauchen Unit-Tests, denn sie bilden die Basis für einen vertrauenswürdigen Code. (Und solch nützlicher Code kann auch öffentlich sein; weniger nützlich ist geschützter Code.
Ich möchte Ihnen eine Regel vorstellen, die ich über das Testen habe und die besonders mit diesem Thema zusammenhängt:
Ich denke, dass man niemals Produktionscode anpassen sollte, um um das Schreiben von Tests zu erleichtern.
In anderen Beiträgen werden einige Vorschläge gemacht, wie man die Originalklasse anpassen kann, um eine private Methode zu testen. Wenn Sie die Zugänglichkeit einer Methode/eines Feldes in package private oder protected ändern, nur um sie für Tests zugänglich zu machen, dann vereiteln Sie den Zweck der privaten Zugriffsrichtlinie.
Warum sollten wir überhaupt private Felder/Methoden/Klassen haben, wenn wir eine testgetriebene Entwicklung haben wollen? Sollten wir alles als Paket privat oder sogar öffentlich deklarieren, damit wir ohne Aufwand testen können? - Das glaube ich nicht.
Aus einem anderen Blickwinkel betrachtet. Tests sollten die Leistung und Ausführung der Produktionsanwendung nicht beeinträchtigen. Wenn Sie den Produktionscode ändern, nur um die Tests zu vereinfachen, können Sie die Leistung und die Ausführung der Anwendung in irgendeiner Weise beeinträchtigen. Und wenn man anfängt, den privaten Zugriff auf das Paket private zu ändern, kann man schließlich auf "geniale Ideen" kommen, um der ursprünglichen Klasse weiteren Code hinzuzufügen, der die Lesbarkeit zusätzlich beeinträchtigt und die Leistung der Anwendung beeinträchtigen kann.
Andererseits eröffnen Sie mit der Änderung des privaten Zugriffs in einen weniger restriktiven Zugriff einem Entwickler die Möglichkeit, eine neue Situation bei der künftigen Entwicklung der Anwendung zu missbrauchen. Anstatt ihn zu zwingen, auf die richtige Art und Weise zu entwickeln, eröffnen Sie ihm neue Möglichkeiten und geben ihm die Fähigkeit, in Zukunft falsche Entscheidungen zu treffen.
Natürlich kann es ein paar Ausnahmen von dieser Regel geben, aber man sollte sich darüber im Klaren sein, was die Regel und was die Ausnahme ist und warum sie gemacht wird.
Dies ist zwar ein guter Grundsatz, aber ein anderer ist, dass der Code testbar sein sollte. Wenn die Transformation, die der Code durchführen soll, einfach zu verstehen und in kleine Teile zu zerlegen ist (z. B. das Parsen von JSON), sollte das Testen der öffentlichen API ausreichend sein. Wenn der Code mehrere komplizierte Berechnungen durchführt, um das Endergebnis zu erzielen (z. B. ein Kalman-Filter), kann das Testen der einzelnen Schritte des Algorithmus die Prüfung erleichtern. Vor allem das Testen der privaten Methoden kann zeigen, wo das Problem liegt.
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!