2016-06-10 10 views
0

Ich habe eine C# -Projektbibliothek DLL mit einer internen Klasse, und ich möchte Einheit testen. Ich möchte diese interne Klasse speziell testen, indem ich, wenn möglich, einen Verweis auf die interne Klasse verwende.Wie kann ich mithilfe von Reflection eine Methode für diese interne Klasse aufrufen, die in einer Bibliothek vorhanden ist?

Ich habe diese Klasse:

namespace ProjectA.B.C 
{ 
    class Caching 
    { 
     public static void DoWork() { } 
    } 
} 

Wie kann ich die DoWork Methode mithilfe von Reflektion aus einem anderen Projekt aufrufen, die ProjectA verwendet? Ich habe versucht, aber meine erste Frage ist, dass typeof(ProjectA.B.C.Caching) geschützt ist, so dass ich nicht scheinen kann, noch die Typ-Referenz zu bekommen, aber ich bin sicher, dass es einen Weg gibt.

Der Fehler ist:

‚ProjectA.B.C.Caching‘ unzugänglich ist aufgrund seiner Schutzstufe

+0

Es ist nicht geschützt - es ist intern. Sie können 'Assembly.GetType' verwenden, obwohl ... haben Sie das schon probiert? –

+0

@JonSkeet Ich habe meine Frage aktualisiert, bin aber immer noch nicht sicher, wie ich die Assembly-Referenz erhalten soll. – Alexandru

+0

wablab Antwort ist ein besserer Ansatz, eigentlich ... –

Antwort

2

Sie können die InternalsVisibleToAttribute verwenden die interne Klasse sichtbar zu Ihrem Unit-Test-Projekt zu machen.

https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx

+0

Guter Ansatz, es funktioniert, ich mag es, ich werde es benutzen; immer noch interessiert an einer Reflektionsantwort, aber was ist der Umfang dieser Frage? – Alexandru

+1

Angenommen, der Name der Assembly lautet "ProjectA", können Sie Folgendes tun: var t = Type.GetType ("ProjectA.B.C.Caching, ProjectA"); var m = t.GetMethod ("DoWork"); m.Invoke (null, null); – wablab

0

Wenn das andere Projekt hat den Namen ProjectA.B.C und spuckt eine Assembly namens ProjectA.B.C, und es hat die folgende interne Klassenimplementierung mit den folgenden Methodensignaturen und den folgenden Namespace:

namespace ProjectA.B.C 
{ 
    class Caching 
    { 
     public static bool GetOrSet<T>(string key, Func<T> getValue, out T value, TimeSpan? expiration = null) { 
      ... 
     } 
     public static bool Get<T>(string key, out T value) { 
      ... 
     } 
    } 
} 

Sie können es so für Unit-Test nennen:

var type = Assembly.Load("ProjectA.B.C").GetTypes().First(x => x.Name.Equals("Caching", StringComparison.Ordinal)); 
var methods = type.GetMethods(); 
var getOrSetMethod = methods.First(x => x.Name.Equals("GetOrSet", StringComparison.Ordinal) && x.ReturnType.Name.Equals("Boolean", StringComparison.Ordinal)).MakeGenericMethod(typeof(bool)); 
var getMethod = methods.First(x => x.Name.Equals("Get", StringComparison.Ordinal)).MakeGenericMethod(typeof(bool)); 
var resultToSet = true; 
Func<bool> action =() => { return resultToSet; }; 
if (!(bool)getOrSetMethod.Invoke(null, new object[] { "GetOrSet", action, resultToSet, (TimeSpan?)null })) 
    throw new Exception("Could not set the GetOrSet key to a boolean value of true."); 
var parameters = new object[] { "GetOrSet", resultToSet }; 
if (!(bool)getMethod.Invoke(null, parameters)) 
    throw new Exception("Could not get back the GetOrSet key."); 
if ((bool)parameters[1] != true) 
    throw new Exception("Got the wrong GetOrSet key back."); 

T er oben zeigt, wie Sie können:

  • Generische Funktionsparameter erstellen.
  • Invoke Methoden mit Generika von MakeGenericMethod(params Type[] typeArguments) verwenden.
  • Rufen Sie Methoden mit out Parametern auf und überprüfen Sie das zurückgegebene Parameter-Array für das Ergebnis.