2017-09-14 8 views
0

特定のエッジケースをテストするための単体テストを作成しようとしています。クラスのプライベートプロパティを保持するためにReflectionを使用しています。C#Reflection SetValue

Iは

var getPrivateProperty = obj.GetType().GetProperty("somename", BindingFlags.Instance | BindingFlags.NonPublic); 
getPrivateProperty.SetValue(obj, newValue, null); 

を使用することができる一方で、私が持っている問題は、プロパティは、クラス内のNULLに設定されており、この方法では、オブジェクトのインスタンスに次に設定されることです。

:私の特定のテストでは、私はこれを試してみました私は、オブジェクトのインスタンスにこのプロパティを設定する必要がありますが、私はまだ「オブジェクトのインスタンスに設定されていない

オブジェクトの悪名高いエラーを取得しています

getPrivateProperty.SetValue(obj, new List<string>() {item, item2}, null); 

私のテストを完了するために、オブジェクトのインスタンスであるためにプロパティを設定する方法はありますか?

+2

マーク性内部および使用[ 'InternalsVisibleToAttribute'(https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute。 aspx)をテストプロジェクトと一緒に使用します。 – Romoku

+0

何がnullであるかを把握し、それにnullを与えないでください。 –

+2

あなたは、あなたが反映しているクラスを含む[mcve]を投稿できますか?あなたが作業しているものを正確に知らなくてもリフレクションの問題をデバッグするのは難しいです。 –

答えて

1

は、あなたのテストプロジェクトでInternalsVisibleToAttributeを使用することを検討して脆弱な反射を避けるために。

プロジェクトのよく知られている場所に属性を置きます。 ASP.NET 4のApp_StartやASP.NETコアのプロジェクトルートのようなところです。

AssemblyAttributes.cs

[assembly:System.Runtime.CompilerServices.InternalsVisibleTo("SomeProject.Tests")] 

はその後internalとしてあなたprivateフィールドをマーク。

public class Foo 
{ 
    internal string Bar; 

    public void MethodThatUsesBar() 
    { 
    } 
} 

これで、テストプロジェクトはinternalフィールドを参照できます。

public class FooTests 
{ 
    public void TestMethodThatUsesBar() 
    { 
     var foo = new Foo { Bar = "This works now" }; 
     foo.MethodThatUsesBar(); 
     // Some Assertion 
    } 
} 

もう一つの方法は、Microsoft.VisualStudio.TestTools.UnitTestingからPrivateObjectを使用することです。

私はこのコードを試してみました
public class FooTests 
{ 
    public void TestMethodThatUsesBar() 
    { 
     var foo = new Foo(); 
     var fooWrapper = new PrivateObject(foo); 
     fooWrapper.SetField("Bar", "This works too."); 

     foo.MethodThatUsesBar(); 

     // Some Assertion 
    } 
} 
+0

彼は内部プロパティではなくプライベートプロパティを設定します。しかし、これは、その場合のきめ細かな解決策です。 – thisextendsthat

0

:あなたは "の宣言を変更した場合、コメントで示唆されているように、

var foo = new Foo(); 
var fooType = foo.GetType(); 
var somenameProperty = fooType.GetProperty("somename", BindingFlags.Instance | BindingFlags.NonPublic); 
somenameProperty.SetValue(foo, new List<string>() { "abc", "def" }, null); 

、それは動作しますが、:

public class Foo 
{ 
    private List<string> somename { get; set; } 
} 

、その後、 somename 'プロパティをフィールドにする場合、GetPropertyの代わりにGetFieldを使用する必要があるため、' somenameProperty 'はnullになります。

public class Foo 
{ 
    private List<string> somename; 
} 

、次いで:

var foo = new Foo(); 
var fooType = foo.GetType(); 
var somenameField = fooType.GetField("somename", BindingFlags.Instance | BindingFlags.NonPublic); 
somenameField.SetValue(foo, new List<string>() { "abc", "def" });