12 Jan
2009

Reflection Helper for DTO Testing

Category:General PostTag: :

I been using the DTO / ViewModel approach to encapsulate UI data for approximately 18 months. During that time the resulting DTOs have gradually flattened out as I took the technique to it’s logical extreme. Currently I only expose strings. Originally I was exposing domain objects and / or other primitive types and this was resulting in some untestable logic hidden in GridViews etc. which I didn’t like.

Some of the problems that must be solved with this technique include how to populate the DTOs and how to test that each property returns what is expected. Initially I simply used NHibernate’s Projection ability to populate the DTO directly. However the need to flatten has led to business (display) logic bleeding into the DTO. In addition because I don’t have access to domain logic during a Projection because I only have access to the mapping file (e.g. I don’t know that FullName = FirstName + ", " + LastName). This leads to duplication which of course is bad. An alternative to the Projection approach is to use a mapping class that transforms from the domain to the DTO. I have not been using this technique but I am going to experiment with it because currently my DTOs are violating the Single Responsibility Principle.

However today I need to the ability to test the internal DTO mapping logic. This would be a typical example:

protected DateTime CreateDateInternal { get; set; }
public string CreateDate { get { return CrerateDateInternal.ToString(DateHelper.DateFormat); } }

Note the naming convention. NHibernate uses Reflection to set properties so the fact that the "Internal" property is protected is not an issue there. And this is good because it allows me to hide the details of what is going on internally from the consuming UI widget. But the protected property does cause an issue for testing. However the naming convention along with some lambda / expression magic allows us to use a form of type safe Reflection and greatly simplify my tests. This allows me to do this:

[Test]
public void CreateDate_Converts_CreateDateInternal_To_Correctly_Formatted_String()
{
    var dto = new TestDTO();
    ReflectionHelper.SetProtectedInternal(dto, x => x.CreateDate, new DateTime(2008, 1, 1));
    Assert.AreEqual("01/01/2008", welderDTO.CreateDate);
}

Here’s the code from the helper class that makes this possible:

public static void SetProtectedInternal<T>(T instance, Expression<Func<T, object>> expression, object value)
{
    Type type = typeof(T);
    var memberExpression = (MemberExpression)expression.Body;
    PropertyInfo propertyInfo = type.GetProperty(memberExpression.Member.Name + "Internal",
      BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic);
    propertyInfo.SetValue(instance, value, null);
}

2 thoughts on “Reflection Helper for DTO Testing

  1. I prefer a reflection-less approach for testing internals. In your example you would create a class in your test project that inherits from whatever class has the protected internal member. In that class you can add a ctor that takes an expected create date, set the protected internal member which you now have access to, and voila, test your internals without reflection.

  2. Oh, and don’t forget this guy in your AssemblyInfo.cs in the project containing the DTOs,
    [assembly: InternalsVisibleTo(“YourTestAssembly”)]

Comments are closed.