I’ve been spending much of my time working on a multi-tier system that makes use of special purpose data transfer objects for communication between the service tier and various clients.

These dedicated data transfer objects need to be properly marked up with [DataContract] and [DataMember] attributes, else the object is incomplete when transferred over the wire.

Unfortunately, any errors in the markup weren’t apparent at compile time. Instead, they were being discovered either at runtime, when a service call failed outright, or while writing client code, when an expected property was missing from a proxy generated by svcutil.

Enter NUnit to save the day with a cunning unit test.

[Test]
public void PublicPropertiesOfDataTransferObjects_shouldHaveDataMemberAttribute()
{

We begin by finding all the candidate data transfer object classes - every descendant of the base class DataTransferObject found in the appropriate assembly.

var dtoTypes
    = typeof(InstrumentDTO).Assembly
        .GetExportedTypes()
        .Where(t => typeof(DataTransferObject)
                    .IsAssignableFrom(t))
        .ToList();

Then we iterate over all the properties declared on those classes to find all the properties that have not been flagged with either [DataMember] or [IgnoreDataMember]. The later attribute allows you to explicitly opt out of the data contract serializer if you want.

var invalidProperties
    = dtoTypes.SelectMany(t => t.GetProperties())
        .Where(p => !PropertyHasDataMemberAttribute(p)
            && !PropertyHasIgnoreDataMemberAttribute(p))
        .ToList();

The test needs to do more than fail the build if there is a problem. It also needs to tell us where to fix the problem, so we generate a diagnostic message listing all of the invalid properties.

var violations
    = "Found "
      + invalidProperties.Select(
          p => string.Format("{0}.{1}", 
                             p.DeclaringType.Name, 
                             p.Name))
            .JoinWith("; ");

JoinWith() is a simple utility extension method that combines a sequence of strings together with a specified separator.

With all of the information gathered in, we can write our test to ensure that there are no invalid properties in our project.

    Assert.That(invalidProperties.Count, 
                Is.EqualTo(0), 
                violations);
}

NUnit can be used for more than testing the functionality of small pieces of code - it can also be used to enforce coding conventions and to catch problems early.

Do you have a critical convention in your system that could be enforced by this kind of an assembly wide unit test?

Comments

blog comments powered by Disqus
Next Post
CallerInfo in C# 5  08 Dec 2011
Prior Post
When Live Mesh fails  19 Nov 2011
Related Posts
Error Methods  25 Nov 2017
Pass implementations, not representations  14 Oct 2017
Avoiding the Singleton Pattern  22 Jul 2017
Implementing the Singleton Pattern  15 Jul 2017
Static Analysis tools for the Win  15 Apr 2017
Exception Logging  19 Jan 2016
On the Merits of Simple Code  28 Nov 2015
Semantic Types  27 Sep 2015
Command Line Processing  21 Sep 2014
Easy String Conversion  24 Aug 2014
More smart-code posts »
Related Pages
December 2011 archive