2017-09-14 83 views
0

我想創建一個單元測試來測試一個特定的邊界情況,並且我正在使用Reflection來獲得一個類的私有屬性。C#反射SetValue

雖然我可以用

var getPrivateProperty = obj.GetType().GetProperty("somename", BindingFlags.Instance | BindingFlags.NonPublic); 
getPrivateProperty.SetValue(obj, newValue, 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。 –

+2

你可以發佈一個[mcve]包括你正在反思的類嗎?調試反射問題很困難,不知道你在做什麼。 –

回答

1

爲了避免脆弱的反射考慮使用InternalsVisibleToAttribute與你的測試項目。

將該屬性放置在項目中衆所周知的位置。某處像ASP.NET 4中的App_Start或ASP.NET Core中的項目根目錄。

AssemblyAttributes.cs

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

然後標記您的private場爲internal

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

我試着用這個代碼:

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

然後:

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); 

和它的作品,但是,作爲意見建議,如果你改變的聲明「 somename'屬性成爲字段,則'somenameProperty'將爲空,因爲您應該使用GetField而不是GetProperty:

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" });