Calling Non Public Setters

Properties with non public setters sometimes make sense – until a unit test requires an object to be set up in a specific state. I don’t want to make the setter public just because of the tests, so I wrote a small helper function that can call non public setters.

The helper returns the object itself, to allow a fluent syntax inside member initialization expressions and uses a lambda to select the member (I do like compile time checking whenever it’s possible).

This is actual code I wrote last week using the helper. It’s part of a set up of an object collection used for unit tests.

Orders = new List<Order>
{
  new Order
  {
    OrderId = 983427,
  }.CallNonPublicSetter(o => o.StatusId, OrderStatus.Confirmed),
  new Order
  {
    OrderId = 18956,
  }.CallNonPublicSetter(o => o.StatusId, OrderStatus.Delivered)
};

The helper is implemented using reflection to access the property to bypass the protection level of the setter.

static class NonPublicSetter
{
  public static TObject CallNonPublicSetter<TObject, TProperty>(this TObject obj,
    Expression<Func<TObject, TProperty>> property, TProperty value)
  {
    var memberExp = (MemberExpression)property.Body;
 
    ((PropertyInfo)memberExp.Member).SetValue(obj, value);
 
    return obj;
  }
}

Using reflection to bypass a class’ protection and access protected or private members is not recommended in production code – but for unit tests I think it makes perfect sense. In the sample above from last week, it’s of course possible to create an object and bring it through a number of operations to put it in the required state. That’s what happens in the production code. But for a unit test it’s just awkward to have to push an object through three or four state transitions just to get it set up for a test of a later state transition. It’s much better to just set up the object to be in a known state and then call the method being tested.

  • Pete Jaffe on 2013-05-28

    I wanted to make sure that you were aware of the InternalsVisibleToAttribute (http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx).

    I sometimes end up compromising and making a property (or method) internal rather than protected/private in order to leverage this attribute and allow my test fixtures (that are in another assembly) to have direct compile references against internal members in the assembly being tested. This can provide better support for refactoring and code analysis. Although, I have mixed feelings about that, because it clearly exposes those properties for undesired use within the assembly.

    When using your approach with reflection, at least your unit test failures will be pretty immediate and draw attention to issues.

    • Anders Abel on 2013-05-28

      Thanks for commenting and mentioning InternalsVisibleToAttribute. I’m aware of it, and have used it, but find it rather messy to work with. It also requires stuff to be internal which as you say is a compromise.

      I think that for the limited case to just call a few non public setters my helper method is a more lightweight approach and removes the need for adjusting the code being tested.

  • Leave a Reply

    Your name as it will be displayed on the posted comment.
    Your e-mail address will not be published. It is only used if I want to get in touch during comment moderation.
    Your name will be a link to this address.
Software Development is a Job – Coding is a Passion

I'm Anders Abel, a systems architect and developer working for Kentor in Stockholm, Sweden.

profile for Anders Abel at Stack Overflow, Q&A for professional and enthusiast programmers

The complete code for all posts is available on GitHub.

Popular Posts

Archives

Series

Powered by WordPress with the Passion for Coding theme.