2009-11-06 11 views
16

Ich habe eine Klasse namens "Session", die mehrere öffentliche Methoden verfügbar macht. Ich möchte Unit-Test diese, aber in der Produktion muss ich die Instantiierung von "Session" -Objekten zu steuern, so delegieren Konstruktion zu einer SessionManager-Klasse und haben den Konstruktor der Sitzung intern gemacht.Unit Testen einer Klasse mit einem internen Konstruktor

Ich möchte idealerweise die Session-Klasse isoliert vom SessionManager testen, der sie erstellt, um zu beweisen, dass die von der Session offengelegten öffentlichen Schnittstellen wie erwartet funktionieren - aber eine Session aus einem Test nicht ohne Instanz instanziieren können ein SessionManager macht meine Tests komplizierter/weniger nützlich als sie sein müssen.

Was ist der beste Weg, damit umzugehen?

Prost,

Lenny.

+0

Plese clear up: ist Es ist ein geschützter ___ oder ein interner Konstruktor? –

Antwort

42

Nichts hindert Sie von Test Interna einfach die Einbauten des Codes machen, um die Testsuite sichtbar, durch das InternalsVisibleTo Attribut:.. in der Assembly, fügen

[assembly:InternalsVisibleTo("TestSuiteAssembly")] 
+0

Dies scheint der einfachste Weg zu sein, also denke ich, dass ich damit laufen werde. Vielen Dank. –

+1

Die Antwort ist wirklich nicht vollständig - die Baugruppen müssen signiert sein, damit es funktioniert. – Santhos

+0

@Santhos nicht wirklich ... –

2

Sie könnten Ihre Unit-Testklasse einfach von Session erben lassen (vorausgesetzt, Ihr Test-Framework erfordert nicht, dass Sie von einer bestimmten Klasse erben). Zum Beispiel mit NUnit:

[TestFixture] 
public class SessionTest : Session 
{ 
    public SessionTest() 
     : base() // call protected constructor 
    { 
    } 

    [Test] 
    public void TestSomething() 
    { 
    } 

} 
+1

OP sagte ctor ist intern, nicht geschützt. –

+0

@Rex - der Titel der Frage sagt geschützt, während die Frage selbst intern sagt. –

1

Sie möchten ein Produkt wie TypeMock verwenden, die Sie verspotteten erstellen können (gefälschte) Instanzen von Klassen, wie folgt aus:

var myInstance = Isolate.Fake.Instance<Session>(); 
// mock behavior here 
// do assertions here 

Sie Instanzen erstellen können von abstrakten Klassen mit TypeMock auch für den Datensatz.

+3

die gleiche Klasse zu verspotten, die du testen willst, macht mir aber keinen großen Sinn ... würdest du nicht den Mock und nicht die Klasse testen? – Svish

+0

@Swish, Sie sind richtig, dass gefälschtes Verhalten nicht nützlich ist, aber es kann auch echte Instanz erstellen und das Problem der Barrierefreiheit lösen: Isolate.Fake.Instance (Members.CallOriginal). Auf diese Weise haben Sie eine tatsächliche Instanz der Klasse, auf deren Konstruktor nicht zugegriffen werden kann. Haftungsausschluss - Ich arbeite bei Typemock. – Elisha

2

Alternativ können Sie als Problemumgehung auch eine Testsitzung erstellen, die von Sitzung erbt und einen öffentlichen Konstruktor verfügbar macht. In Ihrem Unit-Test verwenden Sie dann die TestSession, die im Grunde das gleiche wie das ursprüngliche Session-Objekt ist.

public class TestSession : Session 
{ 

    public TestSession() : base() 
    { 

    } 

} 
1

Ich würde den Wert in Frage stellen, den Sitzungsklassenkonstruktor intern zu machen.

Im Allgemeinen bedeutet dies, dass Sie versuchen, andere Entwickler daran zu hindern, Ihre Klasse zu verwenden. Vielleicht wäre es besser zu kommunizieren, wie dieser Teil der Anwendung funktioniert und warum Sie nur vom Sitzungsmanager auf die Sitzung zugreifen möchten?

+0

Ich habe gesehen, dass es mit einem Fabrikmodell sehr viel erreicht wurde, wo man vielleicht durchsetzen muss, dass die Klasse immer nur an einem Ort erstellt oder zerstört wird, aber andere Leute können es referenzieren und benutzen. –

+0

Ich habe es auch oft gesehen :) Ich sehe einfach nicht, wie es einen Wert hinzufügt. Es verursacht nur Probleme, wenn Sie erweitern oder testen möchten - so wie Leonard es jetzt erlebt. MS ist einer der schlimmsten Täter in dieser Hinsicht, es gibt eine Tonne von internen Klassen, die manchmal nützlich sein könnten, aber wir können einfach nicht darauf zugreifen! Frustration! –

+5

Als jemand, der ein Verbraucher von APIs war, und war sehr frustriert wie Sie sich fragen, warum MS so viele Dinge intern, geschützt usw. macht. Jetzt mache ich hauptsächlich API-Entwicklung und mein Zeug wird von anderen Entwicklern verbraucht. Ich verbringe viel Zeit damit, andere Leute aufzuräumen, weil sie sich selbst in Schwierigkeiten bringen, indem ich Sachen benutze, die ich intern hätte machen sollen. Manchmal ist es nicht realistisch zu erwarten, dass wir in der Lage sind, jeden Code, den wir schreiben, "richtig" zu verwenden. –

0

Wenn Sie mit dem Konstruktor "protected internal" fortfahren können, können Sie das Attribut InternalsVisibleTo zu Ihrer "zu testenden Assembly" hinzufügen, vorausgesetzt, dass sich Ihre Tests in einer anderen Assembly befinden. Dies würde es ermöglichen Ihre Tests interne Mitglieder zu sehen sein geprüft-Montage“.

aktualisieren Aus irgendeinem Grund habe ich gelesen, dass Ihr Konstruktor geschützt wurde. Es ist bereits intern, so dass Sie in einer guten Position sind, verwenden dieses Attribut

Verwandte Themen