Posts
203
Comments
1117
Trackbacks
51
January 2009 Entries
Validation Application Block – Unit Test Validation Logic

The Enterprise Library Validation Application Block (VAB) is a great library for putting your validation in your business layer where it belongs rather than in the UI. It allows us to apply attributes to the properties of our business objects like this:

   1:  public class Person
   2:  {
   3:      [StringLengthValidator(1, 20, MessageTemplate="First Name must be between 1-20 characters.")]
   4:      public string FirstName { get; set; }
   5:   
   6:      [StringLengthValidator(1, 20, MessageTemplate="Last Name must be between 1-20 characters.")]
   7:      public string LastName { get; set; }
   8:  }

But are you unit testing your validation code properly? Consider this test method:

   1:  [TestMethod]
   2:  public void Person_Validation_Test()
   3:  {
   4:      var person = new Person();
   5:      person.FirstName = "Bill";
   6:      person.LastName = "Gates";
   7:   
   8:      // Verify person is valid
   9:      var validationResults = Validation.Validate(person);
  10:      Assert.IsTrue(validationResults.IsValid, "Person should be valid.");
  11:   
  12:      // Now make first name invalid
  13:      person.FirstName = string.Empty;
  14:      validationResults = Validation.Validate(person);
  15:      Assert.IsFalse(validationResults.IsValid, "Validation failed. FirstName should have been invalid.");
  16:   
  17:      // Now make last name invalid
  18:      person.FirstName = "Bill";
  19:      person.LastName = string.Empty;
  20:      validationResults = Validation.Validate(person);
  21:      Assert.IsFalse(validationResults.IsValid, "Validation failed. LastName should have been invalid.");
  22:  }

At first glance, this test method might look ok. It tests the person to make sure it’s valid; it then makes FirstName invalid and then tests it; it then makes LastName invalid (while setting FirstName back to normal) and then tests it, etc.  But actually, there is a long list of things that are *wrong* with that test method – do *not* unit test this way. 

First off, a good unit test should only test ONE thing at a time.  In other words, you should have a test method for the FirstName property, another for the LastName property, etc.  In fact, you could have a test method for FirstName being string.Empty, another test method proving that FirstName is invalid when it is over 20 characters, etc.  Additionally, trying to “reset” the FirstName property back to normal before testing the LastName validation is just asking for trouble.  A test method constructed in this way is going to get monolithic and ultimately you’re going to forget to “reset” properly.  Additionally, you want to strive for DRY (Don’t Repeat Yourself) in your unit tests and how many times do you want to “reset” various properties back to “normal”?

If that wasn’t enough, there is something even more harrowing with this test.  That is: after FirstName is set to string.Empty and validity checked for, how do we *know* that the FirstName property is the thing that is causing this object to be invalid?  Sure, it looks obvious from the method but it’s not explicit and it’s uncertain. What if setting the FirstName property actually made some composite validator invalid but the FirstName itself was perfectly valid?  What if, when we got to the LastName validation, we didn’t remember to properly “reset” the FirstName property and we’re asserting LastName is invalid where it was really the FirstName test that came before it that was making it invalid? There are just too many opportunities to make mistakes.  To simplify all of this, the unit tests can be re-written like this:

   1:  [TestMethod]
   2:  public void Person_FirstName_Is_Invalid()
   3:  {
   4:      var person = CreateValidPerson();
   5:      person.FirstName = string.Empty;
   6:      person.AssertWithKey("FirstName");
   7:  }
   8:   
   9:  [TestMethod]
  10:  public void Person_LastName_Is_Invalid()
  11:  {
  12:      var person = CreateValidPerson();
  13:      person.LastName = string.Empty;
  14:      person.AssertWithKey("LastName");
  15:  }
  16:   
  17:  public static Person CreateValidPerson()
  18:  {
  19:      var person = new Person();
  20:      person.FirstName = "Bill";
  21:      person.LastName = "Gates";
  22:   
  23:      ValidationResults validationResults = Validation.Validate(person);
  24:      Assert.IsTrue(validationResults.IsValid, "Person should be valid.");
  25:      return person;
  26:  }

Notice that each test method is testing only one property (you can fill in additional test methods to ensure it’s invalid when over 20 characters, etc.).  Additionally, each test starts from a known, valid state by re-using the static CreateValidPerson() method (which, inside, Asserts that it is, in fact, valid).  Most importantly, for each test, it uses the AssertWithKey() method to ensure that the *reason* it is invalid is, in fact, the property we’re interested in.  This AssertWithKey() is a simple extension method:

   1:  public static void AssertWithKey<T>(this T target, string keyToCheck)
   2:  {
   3:      ValidationResults validationResults = Validation.Validate(target);
   4:      ValidationResult result = validationResults.FirstOrDefault(r => r.Key == keyToCheck);
   5:      Assert.IsNotNull(result, "Validation Failed. {0} should have been invalid.", keyToCheck);
   6:  }

Notice the use of the FirstOrDefault() extension method.  The ValidationResults returned from the Validate() method is a collection which we can inspect to ensure that the key (the key is the property name) is tied to the validation result we are looking for and expecting – thus, ensuring that the test is in fact invalid *because* of the specific property we’re testing.

The above code was written for MSTest but can be easily adapted to NUnit, xUnit, or your unit testing framework of choice.

Posted On Tuesday, January 27, 2009 10:27 PM | Comments (3)
Code Sample for Visual Studio Magazine MVC Article

It turns out the code sample that was posted online for my MVC Visual Studio Magazine article was an older version (based on a previous CTP). The latest version based on the MVC beta can be found here.  Let me know if any problems.

Posted On Tuesday, January 27, 2009 9:16 PM | Comments (0)
Use Lambda expression to create a generic KeyedCollection

The .NET framework ships with an abstract KeyedCollection<TKey, TItem> class.  Basically, all you have to do is implement the GetKeyForItem() method you can could look up any item either by ordinal or a customized key. For example, suppose you had a Person class like this:

   1:  public class Person
   2:  {
   3:      public Guid ID { get; set; }
   4:      public string FirstName { get; set; }
   5:      public string LastName { get; set; }
   6:  }

And suppose you wanted to be able to lookup a Person in the collection either by index or by the FirstName property (yes, a contrived example). You could sub-class the KeyedCollection class like this:

   1:  public class PersonKeyedCollection : KeyedCollection<string, Person>
   2:  {
   3:      protected override string GetKeyForItem(Person item)
   4:      {
   5:          return item.FirstName;
   6:      }
   7:  }

Which would allow you the get a person from the list either by index or by key (in this case the FirstName is my little demo example) like this:

   1:  var list = new PersonKeyedCollection();
   2:  list.Add(new Person() { FirstName = "Steve" });
   3:  list.Add(new Person() { FirstName = "Bob" });
   4:  list.Add(new Person() { FirstName = "Jim" });
   5:   
   6:  Console.WriteLine("Result by key  : " + list["Steve"].ToString());
   7:  Console.WriteLine("Result by index: " + list[0].ToString());

This is all well and good but it becomes a pain when you want to do this for different types and you end up sub-classing the KeyedCollection class a bunch of times just to be able to specify the property you want to use for the key.  You also don’t want a solution that relies on Reflection by specifying the name of the property and invoking it on each call.  Alternatively, you can create a more re-usable solution utilizing generics and lambdas so you can write your code like this:

   1:  var list = new GenericKeyedCollection<string, Person>(p => p.FirstName);

Now you won’t have to sub-class KeyedCollection ever again because you’ve created a re-usable GenericKeyedCollection class.  Here is the complete code implementation:

   1:  public class GenericKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>
   2:  {
   3:      private Func<TItem, TKey> getKeyFunc;
   4:   
   5:      protected override TKey GetKeyForItem(TItem item)
   6:      {
   7:          return getKeyFunc(item);
   8:      }
   9:   
  10:      public GenericKeyedCollection(Func<TItem, TKey> getKeyFunc)
  11:      {
  12:          this.getKeyFunc = getKeyFunc;
  13:      }
  14:  }

There are a couple of key points.  First, we simply utilize the generic System.Func<T, TResult> class that was introduced in .NET 3.5. We use a lambda expression to pass a delegate into the constructor that will be used on each GetKeyForItem() call.  Then inside GetKeyForItem() we simply invoke the delegate passing in the current item.

Posted On Friday, January 23, 2009 4:14 PM | Comments (5)
C# 4.0 Named Parameters for better code quality

Sometimes new features are added to a language which fundamentally change how we do things (e.g., when generics was added to .NET 2.0). However, there are other times when features are added to the language that are “syntax sugar” or “nice to have’s”. My outlook on those items has always been that “syntax sugar” is typically a good thing – if there is some feature that allows the code to be more expressive/readable then that is a great thing. Sure, the IL might not be any different behind the scenes but you want your code to be as understandable as possible and developers that come behind you can easily understand what your intent was.

To that end, I believe that named parameters being added to C# 4.0 is a good thing. I’m certainly not advocating that named parameters be used for every method call but there are several instances where this is going to be helpful in terms of code readabilty. Often you see argument passed to a method and you have no idea what the parameters are for.  Brad Abrams has a nice design guidelines post regarding Enums vs bool arguments which talks about this very thing. He discusses that enums are often a better choice than Boolean for method parameters because they express intent more clearly.  So in the case where you can’t control the method you are already calling, you can use named parameters to better express intent.

Consider this line of code:

   1:  File.Copy("source.txt", "destination.txt", true);

Unless you’re a developer that is already familiar with this method, you can only guess as to what the last Boolean parameter is for.  With C# 4.0 named parameters this code can be written like this to more clearly express intent:

   1:  File.Copy("source.txt", "destination.txt", overwrite: true);

Object initializers, while typically used in the context of LINQ, can also be used as a stand-alone language feature to express intent more clearly. For example, this snippet of code:

   1:  Person person = new Person();
   2:  person.FirstName = "John";
   3:  person.LastName = "Smith";
   4:  person.DateOfBirth = new DateTime(1970, 1, 1);

can be re-written with object initializers like this to be more concise and better express intent:

   1:  Person person = new Person() { FirstName = "John", LastName="Smith", DateOfBirth = new DateTime(1970, 1, 1)};

It’s as if you can use constructor like syntax to initialize the object – but it’s *more* readable than a constructor because the object initializer uses the property names so it’s obvious what is happening and what properties are being assigned to.  Of course, you can only use that type of syntax in C# 3.0 IF all three of those properties have publicly accessible setters.  What happens if you actually do have a constructor definition that looks like this:

   1:  public Person(string firstName, string lastName, DateTime dateOfBirth)

In that case, you have no other option in C# 3.0 other than to invoke the constructor like this:

   1:  Person person = new Person("John", "Smith", new DateTime(1970, 1, 1));

So it’s not 100% obvious what is being assigned in the constructor (e.g., that third DateTime parameter might be date of birth, might be date hired, who knows).  In C# 4.0, you can invoke the constructor like this:

   1:  Person person = new Person(firstName: "John", lastName: "Smith", dateOfBirth: new DateTime(1970, 1, 1));

This expresses intent clearly and makes the code more understandable.  Again, named parameters should not be used gratuitously but there are many instances where it can make your code higher quality.

Posted On Thursday, January 22, 2009 9:51 PM | Comments (13)

View Steve Michelotti's profile on LinkedIn

profile for Steve Michelotti at Stack Overflow, Q&A for professional and enthusiast programmers




Google My Blog

Tag Cloud