Using DeepSet to Clean up Your C# Test Code

We do a lot of tool smithing at Atomic Object. Much of it is small helper classes that make coding easier or prettier. As a case in point I’d like to share a helper class that I built recently to clean up some of the test code in my current project. I call it DeepSet.

In our project we have to make calls into a third party vendor’s library using their data structures. Most of these data structures are very large and nested deeply with classes within classes. Here is a portion of an anonymized input structure:

  public class EngineStatus
  {
    // Lots of Properties...
    public ErrorReport Report { get; set; }
    // Lots more properties...
  }
 
  public class ErrorReport
  {
    // More stuff elidied
    public ErrorFlag Flag { get; set; }
  }
 
  public class ErrorFlag
  {
    public string Name { get; set; }
    public RiskFactor Critical { get; set; }
  }
 
  public class RiskFactor
  {
    public string RiskCode { get; set; }
    public string Description { get; set; }
  }

In many of our tests, only a very few of the properties are of interest and need to be set. While some of the C# 3.0 features make the code cleaner than it might have been a few years ago, it was still pretty verbose:

var status = new EngineStatus
{
  Report = new ErrorReport
  {
    Flag = new ErrorFlag
    {
      Name = "Substantial Error"
      Critical = new RiskFactor
      {
        RiskCode = "THX1138"
        Description = "Bad things, Man."
      }
    }
  }
}

Now, we strive to make out test code as readable as the production code (if not even more so with its use as documentation), so filling a test file with lots of these deeply nested structure initializations is just the sort of thing we try to make better with tool smithing.

DeepSet is the result of this effort. DeepSet allows a test writer to set up a deeply nested data structure in a way that is much easier on the eyes and still clearly describes the intent.

That same block of initialization code using DeepSet would look like this:

var status = DeepSet.Set<EngineStatus>("ErrorReport.ErrorFlag.Name", "SubstantialError");
DeepSet.Set(status, "ErrorReport.ErrorFlag.Critical.RiskCode", "THX1138");
DeepSet.Set(status, "ErrorReport.ErrorFlag.Critical.Description", "Bad things, Man.");

Finally, a little piece of flair was added to clean things up a little more. You can define multiple fields in a single call by using the vertical bar character (|) between field names:

"ErrorReport.ErrorFlag.Critical.RiskCode|Description", "THX1138", "Bad things, Man.");

Try it out by downloading the DLL or source code here.