繁体   English   中英

C#反射SetValue

[英]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.UnitTestingPrivateObject

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM