Reputation: 2405
I am trying to create a unit test to test a specific edge case, and I am using Reflection to get hold of a private property of a class.
Whilst I can use
var getPrivateProperty = obj.GetType().GetProperty("somename", BindingFlags.Instance | BindingFlags.NonPublic);
getPrivateProperty.SetValue(obj, newValue, null);
The issue I have is that the property is set as null in the class and is then set to an instance of object in a method. In my specific test I need to set this property to an instance of an object, but I am still getting the infamous error of
Object not set to an instance of an object". I have tried this:
getPrivateProperty.SetValue(obj, new List<string>() {item, item2}, null);
Is there a way to set the property to be an instance of an object in order to complete my test?
Upvotes: 0
Views: 556
Reputation: 21245
To avoid fragile reflection consider using the InternalsVisibleToAttribute
with your test project.
Put the attribute in a well known location in your project. Somewhere like App_Start
in ASP.NET 4 or the project root in ASP.NET Core.
AssemblyAttributes.cs
[assembly:System.Runtime.CompilerServices.InternalsVisibleTo("SomeProject.Tests")]
Then mark your private
field as internal
.
public class Foo
{
internal string Bar;
public void MethodThatUsesBar()
{
}
}
Now the Test project can reference the internal
field.
public class FooTests
{
public void TestMethodThatUsesBar()
{
var foo = new Foo { Bar = "This works now" };
foo.MethodThatUsesBar();
// Some Assertion
}
}
Another way is to use the PrivateObject
from Microsoft.VisualStudio.TestTools.UnitTesting
.
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
}
}
Upvotes: 1
Reputation: 1193
I tried with this code:
public class Foo
{
private List<string> somename { get; set; }
}
and then:
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);
and it works, but, as suggested in the comments, if you change the declaration of the 'somename' property to become a field, then 'somenameProperty' will be null because you should use GetField instead of GetProperty:
public class Foo
{
private List<string> somename;
}
and then:
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" });
Upvotes: 0