508 Stimmen

Wie testet man private Methoden in der Einheit?

Ich baue eine Klassenbibliothek, die einige öffentliche und private Methoden haben wird. Ich möchte in der Lage sein, die privaten Methoden zu testen (vor allem während der Entwicklung, aber auch es könnte für zukünftige Refactoring nützlich sein).

Wie geht man dabei richtig vor?

3 Stimmen

Vielleicht übersehe ich etwas, oder vielleicht ist diese Frage einfach nur, nun ja... pre-historic in Bezug auf Internet Jahre, aber Unit-Tests von privaten Methoden ist jetzt sowohl einfach und unkompliziert, mit Visual Studio produziert die notwendigen Accessor-Klassen, wenn nötig und Pre-Füllung der Tests Logik mit Schnipseln verdammt nah an das, was man für einfache funktionale Tests wünschen kann. Siehe z.B.. msdn.microsoft.com/de-us/library/ms184807%28VS.90%29.aspx

5 Stimmen

Dies scheint fast ein Duplikat zu sein von stackoverflow.com/questions/34571/ .

0 Stimmen

Der Fragesteller verwendet möglicherweise nicht Visual Studio

21voto

Big Kahuna Punkte 537

Ich denke, dass man sich eine grundsätzlichere Frage stellen sollte: Warum versuchen Sie überhaupt, die private Methode zu testen? Es riecht nach Code, dass Sie versuchen, die private Methode über die öffentliche Schnittstelle der Klasse zu testen, obwohl diese Methode nicht ohne Grund privat ist, da es sich um ein Implementierungsdetail handelt. Man sollte sich nur mit dem Verhalten der öffentlichen Schnittstelle befassen und nicht damit, wie sie im Verborgenen implementiert ist.

Wenn ich das Verhalten der privaten Methode testen möchte, kann ich ihren Code mit Hilfe gängiger Refactorings in eine andere Klasse extrahieren (vielleicht mit Sichtbarkeit auf Paketebene, um sicherzustellen, dass sie nicht Teil einer öffentlichen API ist). Dann kann ich ihr Verhalten isoliert testen.

Das Produkt des Refactorings bedeutet, dass die private Methode nun eine separate Klasse ist, die ein Kollaborateur der ursprünglichen Klasse geworden ist. Ihr Verhalten wird durch ihre eigenen Unit-Tests gut verstanden werden.

Beim Testen der Originalklasse kann ich dann ihr Verhalten nachahmen, so dass ich mich auf das Testen des Verhaltens der öffentlichen Schnittstelle dieser Klasse konzentrieren kann, anstatt eine kombinatorische Explosion der öffentlichen Schnittstelle und des Verhaltens aller privaten Methoden testen zu müssen.

Ich sehe das ähnlich wie beim Autofahren. Wenn ich ein Auto fahre, dann fahre ich nicht mit offener Motorhaube, damit ich sehen kann, dass der Motor funktioniert. Ich verlasse mich auf die Schnittstelle, die das Auto bietet, nämlich den Drehzahlmesser und den Tachometer, um zu wissen, dass der Motor läuft. Ich verlasse mich darauf, dass sich das Auto tatsächlich bewegt, wenn ich das Gaspedal betätige. Wenn ich den Motor testen will, kann ich das auch isoliert tun :D

Natürlich kann das direkte Testen privater Methoden ein letzter Ausweg sein, wenn Sie eine Legacy-Anwendung haben, aber ich würde es vorziehen, dass Legacy-Code umstrukturiert wird, um bessere Tests zu ermöglichen. Michael Feathers hat ein großartiges Buch über genau dieses Thema geschrieben. http://www.amazon.co.uk/Working-Effectively-Legacy-Robert-Martin/dp/0131177052

21 Stimmen

Völlig falsche Logik in dieser Antwort. Der klassische Fall, in dem man eine private Methode braucht, ist, wenn man einen Code braucht, der von öffentlichen Methoden wiederverwendet werden soll. Sie packen diesen Code in eine PrivMethode. Diese Methode sollte nicht öffentlich zugänglich sein, sondern muss getestet werden, um sicherzustellen, dass öffentliche Methoden, die sich auf PrivMethod verlassen, sich auch wirklich darauf verlassen können.

0 Stimmen

Während der anfänglichen Entwicklung macht das Sinn, aber wollen Sie Tests für private Methoden in Ihrem Standard-Regressionsanzug? Wenn ja, kann eine Änderung der Implementierung zu einem Bruch der Testsuite führen. OTOH, wenn Ihre Regressionstests sich nur auf nach außen sichtbare öffentliche Methoden konzentrieren, dann sollte die Regressionssuite den Fehler immer noch erkennen, wenn die private Methode später versagt. Dann können Sie bei Bedarf den alten privaten Test abstauben.

10 Stimmen

Widersprechen Sie, Sie sollten nur die öffentliche Schnittstelle testen, warum sonst die Notwendigkeit für private Methoden. Machen Sie sie in diesem Fall alle öffentlich und testen Sie alle, wenn Sie private Methoden testen, brechen Sie die Kapselung. Wenn Sie eine private Methode testen wollen, die in mehreren öffentlichen Methoden verwendet wird, sollte sie in eine eigene Klasse verschoben und isoliert getestet werden, wobei alle öffentlichen Methoden an diese neue Klasse delegiert werden sollten.

16voto

amazedsaint Punkte 7594

Private Typen, Interna und private Mitglieder sind aus irgendeinem Grund so, und oft möchte man nicht direkt mit ihnen zu tun haben. Und wenn man das tut, ist die Wahrscheinlichkeit groß, dass man später nicht mehr weiterkommt, weil es keine Garantie dafür gibt, dass die Leute, die diese Assemblies erstellt haben, die privaten/internen Implementierungen als solche behalten.

Aber manchmal, wenn ich einige Hacks/Exploration von kompilierten Assemblies oder Assemblies von Drittanbietern durchführe, habe ich selbst den Wunsch, eine private Klasse oder eine Klasse mit einem privaten oder internen Konstruktor zu initialisieren. Oder manchmal, wenn ich mit vorkompilierten Legacy-Bibliotheken zu tun habe, die ich nicht ändern kann, schreibe ich am Ende einige Tests gegen eine private Methode.

So entstand der AccessPrivateWrapper - http://amazedsaint.blogspot.com/2010/05/accessprivatewrapper-c-40-dynamic.html - ist eine schnelle Wrapper-Klasse, die die Arbeit mit den dynamischen Funktionen von C# 4.0 und Reflection erleichtert.

Sie können interne/private Typen erstellen wie

    //Note that the wrapper is dynamic
    dynamic wrapper = AccessPrivateWrapper.FromType
        (typeof(SomeKnownClass).Assembly,"ClassWithPrivateConstructor");

    //Access the private members
    wrapper.PrivateMethodInPrivateClass();

13voto

Unknown Punkte 249

Nun, Sie können private Methoden auf zwei Arten testen

  1. können Sie eine Instanz von PrivateObject Klasse lautet die Syntax wie folgt

    PrivateObject obj= new PrivateObject(PrivateClass);
    //now with this obj you can call the private method of PrivateCalss.
    obj.PrivateMethod("Parameters");
  2. Sie können die Reflexion nutzen.

    PrivateClass obj = new PrivateClass(); // Class containing private obj
    Type t = typeof(PrivateClass); 
    var x = t.InvokeMember("PrivateFunc", 
        BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public |  
            BindingFlags.Instance, null, obj, new object[] { 5 });

0 Stimmen

Gute Antwort, aber für #1 ist Ihre Syntax falsch. Sie müssen eine Instanz von PrivateClass und verwenden Sie diese. stackoverflow.com/questions/9122708/

10voto

philsquared Punkte 22090

Ich habe auch die Methode InternalsVisibleToAttribute verwendet. Es ist auch erwähnenswert, dass, wenn Sie sich unwohl dabei fühlen, Ihre zuvor privaten Methoden intern zu machen, um dies zu erreichen, dann sollten sie vielleicht sowieso nicht Gegenstand direkter Unit-Tests sein.

Schließlich testen Sie die Verhalten Ihrer Klasse und nicht deren spezifische Umsetzung - können Sie letzteres ändern, ohne das erstere zu ändern, und Ihre Tests sollten trotzdem bestehen.

0 Stimmen

Ich finde es gut, dass Sie eher das Verhalten als die Umsetzung testen. Wenn Sie Ihre Unit-Tests an die Implementierung (private Methoden) binden, dann werden die Tests spröde und müssen geändert werden, wenn sich die Implementierung ändert.

9voto

Venkat Punkte 91

Es gibt 2 Arten von privaten Methoden. Statische private Methoden und nicht statische private Methoden (Instanzmethoden). Die folgenden 2 Artikel erklären, wie man private Methoden mit Beispielen testet.

  1. Unit Testing Statische private Methoden
  2. Unit Testing nicht statischer privater Methoden

0 Stimmen

Geben Sie einige Beispiele an, nicht nur einen Link

0 Stimmen

Sieht hässlich aus. Keine Intellisense. Schlechte Lösung von MS. Ich bin schockiert!

0 Stimmen

Der einfachste Weg, private statische Methoden zu testen

CodeJaeger.com

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.

Powered by:

X