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
Using Constructors  27 Feb 2023
An Inconvenient API  18 Feb 2023
Method Archetypes  11 Sep 2022
A bash puzzle, solved  02 Jul 2022
A bash puzzle  25 Jun 2022
Improve your troubleshooting by aggregating errors  11 Jun 2022
Improve your troubleshooting by wrapping errors  28 May 2022
Keep your promises  14 May 2022
When are you done?  18 Apr 2022
Fixing GitHub Authentication  28 Nov 2021
Archives
December 2011
2011