Wednesday, February 23, 2011

How to unit test your DataAnnotations attributes

Earlier on the Twitter, I helped a pal solve a problem they were having with unit testing their DataAnnotations implementation.  He compelled me to blog my solution, and I agree -- what a great subject!

So let's take a pretty common use-case: validating an email address.  Email addresses are a slippery fish, so I'll make a DataAnnotations validator to make sure that an input's value looks like it's probably in a valid email address format.

I start with a regex validator that I think I pulled off of Scott Guthrie's blog:

public class RegexAttribute: ValidationAttribute
{
  public string Pattern { get; set; }
  public RegexOptions Options { get; set; }

  public RegexAttribute(string pattern)
      : this(pattern, RegexOptions.None) {}

  public RegexAttribute(string pattern, RegexOptions options)
  {
    Pattern = pattern;
    Options = options;
  }

  public override bool IsValid(object value)
  {
    //null or empty is valid, let Required handle null/empty
    var str = (string)value;
    return string.IsNullOrEmpty(str) || 
      new Regex(Pattern, Options).IsMatch(str);
  }

}


Simple enough, let's extend it and make an Email validator:

public class EmailAttribute : RegexAttribute
{
  public EmailAttribute() : 
    base(@"^(([^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$", 
    RegexOptions.None) {}
}


Pretty simple.  I bet I could get away with putting it all on one line since no one actually reads regular expressions.

Now here's the magic part.  I'm going to use Reflection to grab all the attributes that are of the type ValidationAttribute and see if those attributes are valid.  If they aren't, I'll make a list of ErrorInfo objects.  I call it my ValidationBuddy.

public static class ValidationBuddy
{
  public static IList<ErrorInfo> GetTypeErrors(object instance)
  {
    var attributes = TypeDescriptor.GetAttributes(instance)
      .OfType<ValidationAttribute>();
      return (from attribute in attributes
              let result = attribute.GetValidationResult(instance, 
          new ValidationContext(instance, null, null))
              where result != null
              select new ErrorInfo(instance.GetType().ToString(), 
          attribute.FormatErrorMessage(string.Empty), 
          instance))
      .ToList();
  }

  public static IList<ErrorInfo> GetPropertyErrors(object instance)
  {
    return (from prop in TypeDescriptor.GetProperties(instance)
      .Cast<PropertyDescriptor>()
        from attribute in prop.Attributes
          .OfType<ValidationAttribute>()
        where !attribute.IsValid(prop.GetValue(instance))
        select new ErrorInfo(prop.Name, 
          attribute.FormatErrorMessage(prop.DisplayName), instance))
         .ToList();
  }

  public static IList<ErrorInfo> GetErrors(object instance)
  {
    var list = GetPropertyErrors(instance);

    foreach (var error in GetTypeErrors(instance))
      list.Add(error);

    return list;
  }
}


The ErrorInfo class is pretty simple, too:

public class ErrorInfo
{
  public ErrorInfo(){}
  public ErrorInfo(string propertyName, string errorMessage, object instance)
  {
    PropertyName = propertyName;
    ErrorMessage = errorMessage;
    Instance = instance;
  }

  public string PropertyName { get; set; }
  public string ErrorMessage { get; set; }
  public object Instance { get; set; }
}


And finally, a single unit test:

[TestMethod]
public void TestEmailValidator05()
{
  // Arrange
  var model = GetModel();
  model.EmailAddress = "uncommonTLD@domain.travel";

  // Act
  var errors = ValidationBuddy.GetErrors(model);

  // Assert
  Assert.IsTrue(!errors.Any());
}


In my actual test class, I have quite a few more tests, but this should get you started in writing your own DataAnnotations unit tests.

Friday, February 18, 2011

What are some important aspects of Object Oriented Design?

I see this a lot in job descriptions and programmer interview questions; "what are the 3 pillars of OOP?"  The first thing you should know is that no two interviewers will agree on any 3 "pillars" of OOP.  But you can start with...

An interface is an ideal thing.  It describes what a thing does, but doesn't bother to elaborate on how it does that thing.  For example, an automobile moves.  An interface doesn't need to know the details of how the automobile moves, but in order for anything to be an automobile, it must move.

A class is a concrete thing.  It provides the implementation of the ideal.  A car is an automobile.  It's easy to see that a car moves, and most people can agree on how a car moves.

One can say that a car is an automobile, but an automobile is not a car.  This is a common mnemonic you can use to determine contravariance (the ability to convert from a narrow type to a wider type).  If you can say that a thing is-a some other thing, then you are describing contravariance in object-oriented design.

Try it out: an arm is-a limb, but a limb is-not-an arm.  Pizza is-a food, but food is-not-a pizza.  Using is-a can help you understand what your ideal object is, and what your concrete object is.

So, back to these important aspects.

Encapsulation.  This is the practice of hiding data by restricting its access to accessors and mutators.  Accessors might be implemented as properties or a get-style functions.  They act as mechanisms to say "you can touch this data, but you have to do it through these knobs & levers.

Abstractions.  A mechanism that is often useful for dealing with complexity.  If you've ever met someone who responds to every problem with a metaphor or proverb, they are using an abstraction.  Using the car/automobile example from above, it can often be easier to solve a problem when looking through the lens of the automobile abstraction rather than trying to fix a car.

Inheritance.  There are three primary relationships in OOP.  Is-a, which we talked about before.  Has-a is used to express composition.  A garage has-a car, or is-composed-of a car.  Uses-a describes a relationship where an object depends on the existence of another object.

Polymorphism.  One name, many forms.  Polymorphism is how object-oriented programmers can shift the lens to look at an object from another angle.  For example, you can look at an arm from the angle of left arm, arm, limb, or organ.  Each form might share some properties just as each form might have its own specific abilities.  A left arm might have a different style of hand, but any arm will have a very similar tricep or bicep.

So do some browsing on your own.  There's so many other people who want to tell you what they think of OOD, it would be a shame if you didn't get several perspectives while developing your own.

Thursday, February 17, 2011

What is SOLID?

I saw this pop up earlier in a list of interview questions and decided that it might be a great way to start seeding my blog -- by answering interview questions.  So, what is SOLID?

SOLID, as it pertains to object-oriented design, is a mnemonic acronym that breaks down into even more acronyms.  It's a tree of acronyms, which might be a fun thing to mention during interviews.

While you could go to Wikipedia entry on SOLID, I'll capture the salient points here as well.

S is for Single Responsibility Principle (SRP).  SRP is a design principle that effectively states that any class should have 1 reason to exist, or 1 reason to change.  When a class does more than one thing, the chances that it will change increase.

O is the Open/Close Principle (OCP).  OCP, in long form, says that classes should be open for extension and closed for modification.  Put another way, only make changes to fix errors.

L is for Liskov Substitution Principle (LSP).  LSP, sometimes known as design by contract or substitutability, simply encourages one to design to an interface, not an implementation.  When discussing substitutability, it's important to understand contravariance and covariance.  The common heuristics here include:

  • Contravariance of method arguments in the subtype
  • Covariance of return types in the subtype

I, the Interface Segregation Principle (ISP), compels one to use multiple simple interfaces rather than fewer complex interfaces.  The net effect is measured by cohesion where high cohesion implies that objects are loosely coupled, low cohesion the opposite.

D for Dependency Inversion Principle (DIP).  Create dependencies on ideal types, not on concrete types.  When talking about dependency inversion, two major points pop up:

  • High level modules should not depend on low level modules.  Both should depend on abstractions.
  • Abstractions should not depend on details, details should depend on abstractions.

For more on DIP, check out these patterns: Adapter, Plugin, Service Locator and Dependency Injection.

Monday, February 14, 2011

Validating an uploaded image file using ASP.NET MVC and DataAnnotations

I recently wrote a feature for a small MVC app that required me to allow a user to upload an image to my web server. This got me wondering "how does a web server know if the file I uploaded is an image file?" There are a few issues to think through:
  • Not every operating system implements file name conventions the same way. Rather, we shouldn't assume that we know anything about the format of the file name we'll receive, it's just a string -- and it may be an empty string.
  • We can't assume that the browser used to upload the file will accurately identify the content type of the uploaded file.
  • The user may upload an image type that they recognize, but our web server does not recognize as an image.
Since this is an ASP.NET MVC app, I started by identifying the Model I want to deal with. Here's my UploadedFileModel:
    public class UploadedFileModel
    {
        [Required, ImageType]
        public HttpPostedFileBase Image { get; set; }
    }
Pretty simple, just one property, nothing too fancy. If you're familiar with DataAnnotations, you'll recognize the Required validator right away. This just checks to see if the property is null when the model is bound to my action.

The other thing one might notice is the ImageType attribute. This is where I put my secret sauce. Take a look:
  public class ImageTypeAttribute : ValidationAttribute
  {
    public override bool IsValid(object value)
    {
      // don't duplicate the Required validator
      if (value == null)
        return true;

      // is it the type we expect?
      if (!(value is HttpPostedFileBase))
        return false;

      // We got this far, is it a recognizable image type?
      var fileStream = ((HttpPostedFileBase) value).InputStream;
      try
      {
        var image = Image.FromStream(fileStream);
      }
      catch
      {
        return false;
      }
      return true;
    }

    public override string FormatErrorMessage(string name)
    {
      return string.Format("{0} is not a valid image format.", name);
    }
  }
At this point, I'm effectively asking the web server if it recognizes whether the posted file as an image type. Yes? Hooray! No? We'll tell the user that it didn't look like a valid image type to us.

Once all that is wired up, we can let the action just do action stuff:
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Insert(UploadedFileModel viewModel)
    {
      if (!ModelState.IsValid)
        return View("Create");

      var model = ImageUtilities.SaveImage(viewModel.Image);

      if (model == null)
      {
        ModelState.AddModelError("Image",
            "File could not be saved, this could happen if the client did not have permission to save the file to disk.");
        return View("Create");
      }

      repository.Add(model);
      return RedirectToAction("Details", new {id = model.Name});
    }
And that's pretty much it. I tried to take advantage of as much default behavior as I could, and I ended up with a validator that I can reuse.