[英]C# Reflection SetValue
我正在尝试创建一个单元测试来测试特定的边缘情况,并且我正在使用Reflection获取类的私有属性。
虽然我可以使用
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);
有没有一种方法可以将属性设置为对象的实例,以完成测试?
为避免脆弱的反射,请考虑在测试项目中使用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
}
}
我尝试使用以下代码:
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”将为null,因为您应该使用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" });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.