Visual Studio ermöglicht das Unit-Testen privater Methoden über eine automatisch generierte Accessor-Klasse. Ich habe einen Test einer privaten Methode geschrieben, die erfolgreich kompiliert wurde, aber zur Laufzeit fehlschlägt. Eine ziemlich minimale Version des Codes und des Tests ist:
//in project MyProj
class TypeA
{
private List<TypeB> myList = new List<TypeB>();
private class TypeB
{
public TypeB()
{
}
}
public TypeA()
{
}
private void MyFunc()
{
//processing of myList that changes state of instance
}
}
//in project TestMyProj
public void MyFuncTest()
{
TypeA_Accessor target = new TypeA_Accessor();
//following line is the one that throws exception
target.myList.Add(new TypeA_Accessor.TypeB());
target.MyFunc();
//check changed state of target
}
Der Laufzeitfehler ist:
Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.
Laut Intellisense - und daher denke ich, dass der Compiler - ist das Ziel vom Typ TypeA_Accessor. Zur Laufzeit ist es jedoch vom Typ TypeA, und daher schlägt das Hinzufügen der Liste fehl.
Kann ich diesen Fehler auf irgendeine Weise stoppen? Oder wahrscheinlich eher, welche anderen Ratschläge andere Menschen haben (ich gehe davon aus, dass "private Methoden nicht testen" und "Unit-Tests den Zustand von Objekten nicht manipulieren lassen").
quelle
Antworten:
Ja, testen Sie keine privaten Methoden. Die Idee eines Komponententests besteht darin, die Einheit anhand ihrer öffentlichen 'API' zu testen.
Wenn Sie feststellen, dass Sie viel privates Verhalten testen müssen, versteckt sich höchstwahrscheinlich eine neue 'Klasse' in der Klasse, die Sie testen, extrahieren und über die öffentliche Schnittstelle testen möchten.
Ein Ratschlag / Denkwerkzeug ..... Es gibt eine Idee, dass keine Methode jemals privat sein sollte. Das heißt, alle Methoden sollten auf einer öffentlichen Schnittstelle eines Objekts leben. Wenn Sie der Meinung sind, dass Sie es privat machen müssen, lebt es höchstwahrscheinlich auf einem anderen Objekt.
Dieser Ratschlag funktioniert in der Praxis nicht ganz, ist aber meistens ein guter Ratschlag, und oft wird er Menschen dazu bringen, ihre Objekte in kleinere Objekte zu zerlegen.
quelle
Sie können die PrivateObject-Klasse verwenden
quelle
"Es gibt nichts, was als Standard oder Best Practice bezeichnet wird, wahrscheinlich handelt es sich nur um populäre Meinungen."
Gleiches gilt auch für diese Diskussion.
Es hängt alles davon ab, was Sie für eine Einheit halten. Wenn Sie UNIT für eine Klasse halten, werden Sie nur die öffentliche Methode anwenden. Wenn Sie glauben, dass UNIT Codezeilen sind, die auf private Methoden treffen, werden Sie sich nicht schuldig fühlen.
Wenn Sie private Methoden aufrufen möchten, können Sie die Klasse "PrivateObject" verwenden und die Methode invoke aufrufen. Sie können sich dieses ausführliche Youtube-Video ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) ansehen, das die Verwendung von "PrivateObject" zeigt und auch erläutert, ob das Testen privater Methoden logisch ist oder nicht.
quelle
Ein weiterer Gedanke hier ist, das Testen auf "interne" Klassen / Methoden auszudehnen, um einen besseren Eindruck von diesen Tests zu vermitteln. Sie können InternalsVisibleToAttribute für die Assembly verwenden, um diese separaten Unit-Test-Modulen auszusetzen.
In Kombination mit einer versiegelten Klasse können Sie sich einer solchen Kapselung nähern, dass die Testmethode nur von der unittesten Montage Ihrer Methoden sichtbar ist. Bedenken Sie, dass die geschützte Methode in der versiegelten Klasse de facto privat ist.
Und Unit-Test:
quelle
Eine Möglichkeit, private Methoden zu testen, ist die Reflexion. Dies gilt auch für NUnit und XUnit:
quelle
call methods
statisch und nicht statisch ?Ähm ... kam hier mit genau dem gleichen Problem mit: Testen Sie eine einfache , aber entscheidende Privatperson Methode. Nach dem Lesen dieses Threads scheint es so zu sein: "Ich möchte dieses einfache Loch in dieses einfache Stück Metall bohren und sicherstellen, dass die Qualität den Spezifikationen entspricht" und dann kommt "Okay, das ist nicht zu einfach. Erstens gibt es dafür kein geeignetes Werkzeug, aber Sie könnten in Ihrem Garten ein Gravitationswellenobservatorium bauen. Lesen Sie meinen Artikel unter http://foobar.brigther-than-einstein.org/ Zuerst natürlich Sie Müssen Sie einige Kurse für fortgeschrittene Quantenphysik besuchen, dann brauchen Sie Tonnen von ultra-coolem Stickstoffium und dann natürlich mein Buch bei Amazon "...
Mit anderen Worten...
Nein, das Wichtigste zuerst.
Jede einzelne Methode, sei es privat, intern, geschützt, öffentlich hat zu prüfbar sein. Es muss eine Möglichkeit geben, solche Tests ohne den hier vorgestellten Lärm durchzuführen.
Warum? Genau weil der architektonischen Erwähnungen, die bisher von einigen Mitwirkenden gemacht wurden. Vielleicht kann eine einfache Wiederholung der Software-Prinzipien einige Missverständnisse beseitigen.
In diesem Fall sind die üblichen Verdächtigen: OCP, SRP und wie immer KIS.
Aber warte eine Minute. Die Idee, alles öffentlich zugänglich zu machen, ist eher weniger politisch und eine Art Haltung. Aber. Wenn es um Code geht, ist dies auch in der Open Source Community kein Dogma. Stattdessen empfiehlt es sich, etwas zu "verstecken", um sich leichter mit einer bestimmten API vertraut zu machen. Sie würden zum Beispiel die Kernberechnungen Ihres neu auf den Markt gebrachten digitalen Thermometer-Bausteins verbergen - nicht, um neugierigen Codelesern die Mathematik hinter der tatsächlich gemessenen Kurve zu verbergen, sondern um zu verhindern, dass Ihr Code von einigen abhängig wird. Vielleicht plötzlich wichtige Benutzer, die nicht widerstehen konnten, Ihren ehemals privaten, internen, geschützten Code zu verwenden, um ihre eigenen Ideen umzusetzen.
Worüber rede ich?
Es ist leicht, das Zeitalter des Wassermanns oder das, was heutzutage genannt wird, zu proklamieren, aber wenn mein Sensor von 1,0 auf 2,0 steigt, kann sich die Implementierung von Translate ... von einer einfachen linearen Gleichung ändern, die leicht verständlich und "neu" ist verwendbar "für alle, für eine ziemlich ausgefeilte Berechnung, die Analyse oder was auch immer verwendet, und so würde ich den Code anderer brechen. Warum? Weil sie die Prinzipien der Software-Codierung nicht verstanden haben, nicht einmal KIS.
Um dieses Märchen kurz zu machen: Wir brauchen eine einfache Möglichkeit, private Methoden zu testen - ohne Umschweife.
Erstens: Frohes neues Jahr allerseits!
Zweitens: Wiederholen Sie Ihren Architektenunterricht.
Drittens: Der "öffentliche" Modifikator ist Religion, keine Lösung.
quelle
Eine andere Option, die nicht erwähnt wurde, besteht darin, die Unit-Test-Klasse als untergeordnetes Element des zu testenden Objekts zu erstellen. NUnit Beispiel:
Dies würde ein einfaches Testen privater und geschützter (aber nicht vererbter privater) Methoden ermöglichen und es Ihnen ermöglichen, alle Ihre Tests vom tatsächlichen Code getrennt zu halten, damit Sie keine Testassemblys für die Produktion bereitstellen. Das Umstellen Ihrer privaten Methoden auf geschützte Methoden ist für viele geerbte Objekte akzeptabel, und es ist eine ziemlich einfache Änderung.
JEDOCH...
Obwohl dies ein interessanter Ansatz zur Lösung des Problems des Testens versteckter Methoden ist, bin ich mir nicht sicher, ob ich befürworten würde, dass dies in allen Fällen die richtige Lösung für das Problem ist. Es scheint ein wenig seltsam, ein Objekt intern zu testen, und ich vermute, dass es einige Szenarien gibt, in denen dieser Ansatz Sie in die Luft jagt. (Unveränderliche Objekte zum Beispiel können einige Tests sehr schwierig machen).
Während ich diesen Ansatz erwähne, würde ich vorschlagen, dass dies eher ein Brainstorming-Vorschlag als eine legitime Lösung ist. Nimm es mit einem Körnchen Salz.
EDIT: Ich finde es wirklich komisch, dass die Leute diese Antwort ablehnen, da ich dies ausdrücklich als schlechte Idee beschreibe. Bedeutet das, dass die Leute mir zustimmen? Ich bin so verwirrt.....
quelle
Aus dem Buch Effektiv mit Legacy-Code arbeiten :
Die Möglichkeit, dies zu beheben, besteht laut Autor darin, eine neue Klasse zu erstellen und die Methode als hinzuzufügen
public
.Der Autor erklärt weiter:
Innerhalb dieser Grenzen besteht Ihre einzige echte Option darin, die Methode
public
entweder in der aktuellen oder in einer neuen Klasse zu erstellen.quelle
TL; DR: Private Methode in eine andere Klasse extrahieren, auf dieser Klasse testen; Lesen Sie mehr über das SRP-Prinzip (Single Responsibility Principle)
Es scheint, dass Sie die
private
Methode in eine andere Klasse extrahieren müssen . in diesem sollte seinpublic
. Anstatt zu versuchen, dieprivate
Methode zu testen , sollten Sie diepublic
Methode dieser anderen Klasse testen .Wir haben das folgende Szenario:
Wir müssen die Logik von testen
_someLogic
; aber es scheint, dassClass A
sie mehr Rolle spielen als nötig (gegen das SRP-Prinzip verstoßen); Refactor einfach in zwei KlassenAuf diese Weise
someLogic
könnte auf A2 getestet werden; In A1 erstellen Sie einfach ein falsches A2 und injizieren es dann in den Konstruktor, um zu testen, ob A2 für die genannte Funktion aufgerufen wirdsomeLogic
.quelle
In VS 2005/2008 können Sie Private Accessor verwenden , um private Mitglieder zu testen. Diese Methode wurde jedoch in späteren Versionen von VS nicht mehr verwendet
quelle