In code, the Law of Demeter (aka the one-dot rule) is a principle that basically states:

void DoSomething(IFoo foo)
{
    foo.GetStatus(); // good
}

void DoSomething(IFoo foo)
{
    foo.Profile.GetStatus(); // bad
}

In this example, DoSomething() knows intimate details about what an IFoo’s insides look like. This is bad because it’s additional coupling that will bog us down later — if we ever want to change the internal composition of IFoo, we will have to also update all pervert methods like DoSomething() that depend on it.

In some situations, this rule really doesn’t matter, e.g. for trivial or built-in types (datasets come to mind). But other times we definitely want to avoid it. One trick I have discovered for identifying trouble spots is a code smell you might encounter when isolating something for unit testing:

var foo = new Mock<IFoo>();
var profile = new Mock<IProfile>();
profile.Setup(p => p.GetStatus()).Returns(/* the thing we are testing */);
foo.SetupGet(f => f.Profile).Returns(profile);

DoSomething(foo.Object); // assert etc 

Does this code look familiar? In it we are setting up two mocks:

  • The Profile instance, which has a method we want to stub out and verify
  • The parent IFoo, which only exists to return the child Profile

The code smell is all the extra setup cruft required — two levels of nested mocks for just one parameter we are testing. If we do move method and provide a GetStatus() method on IFoo (that internally delegates to Profile), our test immediately becomes a lot clearer:

var foo = new Mock<IFoo>();
foo.Setup(p => p.GetStatus()).Returns(/* the thing we are testing */);

DoSomething(foo.Object); // assert etc 
August 26th, 2009 | 4 Comments

Here is a little convention I have adopted for check-in comments when fixing red lights in NUnit:

Red traffic light

  • A failing test is when the issue lies in production code. It fails because the code it is testing has bugs or isn’t fully implemented to spec yet.
  • A buggy test is when the test itself has an issue, and the production code is totally fine. For us these most commonly occur when we forget to set something up e.g. null test objects or unconfigured mocks.
  • A deprecated test fails because the behaviour of the code is now intentionally different than before, and the assertions it makes are no longer valid.

A fourth, more insidious case is the missing test, where possible paths through production code exist without any tests that specify what their behaviour should be. If you’re doing TDD this should never happen, but when it does it can be quite difficult to track down. A coverage tool like NCover can help, but only if you miss a whole block or method. Otherwise you need to use your programmer spidey sense and stay on the look-out for uncovered situations.

Hopefully most of your red lights are due to failing and deprecated tests. If you get a lot of buggy or missing ones, then it probably means you are skipping the red step of red-green-refactor.

August 22nd, 2009 | No Comments Yet

Yesterday I wrote about ASP.NET MVC, TDD and AutoMapper, and how you can use them together in a DDD application. Today I thought I would follow up and explain how to apply these techniques to another important (but boring) part of any web application: user input validation.

To achieve this, we are using Fluent Validation, a validation framework that lets you easily set up validation rules using a fluent syntax:

public class UserRegistrationFormValidator : AbstractValidator<UserRegistrationForm>
{
    public UserRegistrationFormValidator()
    {
        RuleFor(f => f.Username).NotEmpty()
            .WithMessage("You must choose a username!");

        RuleFor(f => f.Email).EmailAddress()
            .When(f => !String.IsNullOrEmpty(f.Email))
            .WithMessage("This doesn't look like a valid e-mail address!");

        RuleFor(f => f.Url).MustSatisfy(new ValidWebsiteUrlSpecification())
            .When(f => !String.IsNullOrEmpty(f.Url))
            .WithMessage("This doesn't look like a valid URL!");
    }
}

If you think about it, validation and view model mapping have similar footprints in the application. They both:

  • Live in the application services layer
  • May invoke domain services
  • Use third-party libraries
  • Have standalone fluent configurations
  • Have standalone tests
  • Are injected into the application services

Let’s see how it all fits together starting at the outermost layer, the controller.

public class AccountController : Controller
{
    readonly IUserRegistrationService registrationService;
    readonly IFormsAuthentication formsAuth;

    ...

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Register(UserRegistrationForm user)
    {
        if (user == null)
            throw new ArgumentNullException("user");

        try
        {
            this.registrationService.RegisterNewUser(user);
            this.formsAuth.SignIn(user.Username, false);
            return RedirectToAction("Index", "Home");
        }
        catch (ValidationException e)
        {
            e.Result.AddToModelState(this.ModelState, "user");
            return View("Register", user);
        }
    }

    ...
}

As usual, the controller is pretty thin, delegating all responsibility (including performing any required validation) to an application service that handles new user registration. If validation fails, all our controller has to do is catch an exception and append the validation messages contained within to the model state to tell the user any mistakes they made.

The UserRegistrationForm validator is injected into the application service along with any others. Just like AutoMapper, we can now test both the controller, validator and application service separately.

public class UserRegistrationService : IUserRegistrationService
{
    readonly IUserRepository users;
    readonly IValidator<UserRegistrationForm> validator;

    ...

    public void RegisterNewUser(UserRegistrationForm form)
    {
        if (form == null)
            throw new ArgumentNullException("form");

        this.validator.ValidateAndThrow(form);

        User user = new UserBuilder()
            .WithUsername(form.Username)
            .WithAbout(form.About)
            .WithEmail(form.Email)
            .WithLocation(form.Location)
            .WithOpenId(form.OpenId)
            .WithUrl(form.Url);

        this.users.Save(user);
    }
}

Testing the user registration form validation rules

Fluent Validation has some nifty helper extensions that make unit testing a breeze:

[TestFixture]
public class When_validating_a_new_user_form
{
    IValidator<UserRegistrationForm> validator = new UserRegistrationFormValidator();

    [Test]
    public void The_username_cannot_be_empty()
    {
        validator.ShouldHaveValidationErrorFor(f => f.Username, "");
    }

    [Test]
    public void A_valid_email_address_must_be_provided()
    {
        validator.ShouldHaveValidationErrorFor(f => f.Email, "");
    }

    [Test]
    public void The_url_must_be_valid()
    {
        validator.ShouldNotHaveValidationErrorFor(f => f.Url, "http://foo.bar");
    }
}

You can even inject dependencies into the validator and mock them out for testing. For example, in this app the validator calls an IUsernameAvailabilityService to make sure the chosen username is still available.

Testing the user registration service

This validation code is now completely isolated, and we can mock out the entire thing when testing the application service:

[TestFixture]
public class When_registering_a_new_user
{
    IUserRegistrationService registrationService;
    Mock<IUserRepository> repository;
    Mock<IValidator<UserRegistrationForm>> validator;

    [Test, ExpectedException(typeof(ValidationException))]
    public void Should_throw_a_validation_exception_if_the_form_is_invalid()
    {
        validator.Setup(v => v.Validate(It.IsAny<UserRegistrationForm>()))
            .Returns(ObjectMother.GetFailingValidationResult());

        service.RegisterNewUser(ObjectMother.GetNewUserForm());
    }

    [Test]
    public void Should_add_the_new_user_to_the_repository()
    {
        var form = ObjectMother.GetNewUserForm();

        registrationService.RegisterNewUser(form);

        service.Verify(
            r => r.Save(It.Is<User>(u => u.Username.Equals(form.Username))));
    }
}

Testing the accounts controller

With validation out of the way, all we have to test on the controller is whether or not it appends the validation errors to the model state. Here are the fixtures for the success/failure scenarios:

[TestFixture]
public class When_successfully_registering_a_new_user : AccountControllerTestContext
{
    [SetUp]
    public override void SetUp()
    {
        ...
        result = controller.Register(form);
    }

    [Test]
    public void Should_register_the_new_user()
    {
        registrationService.Verify(s => s.RegisterNewUser(form), Times.Exactly(1));
    }

    [Test]
    public void Should_sign_in()
    {
        formsAuth.Verify(a => a.SignIn(user.Username, false));
    }
}

[TestFixture]
public class When_registering_an_invalid_user :  AccountControllerTestContext
{
    [SetUp]
    public override void SetUp()
    {
        ...

        registrationService.Setup(s => s.RegisterNewUser(form)).Throws(
            new ValidationException(
                ObjectMother.GetFailingValidationResult()));

        result = controller.Register(form);
    }

    [Test]
    public void Should_not_sign_in()
    {
        formsAuth.Verify(a => a.SignIn(It.IsAny<string>(),
            It.IsAny<bool>()), Times.Never());
    }

    [Test]
    public void Should_redirect_back_to_the_register_view_with_the_form_contents()
    {
        result.AssertViewRendered().ForView("Register")
            .WithViewData<UserRegistrationForm>().ShouldEqual(form);
    }
}

This post has been a bit heavier on code than usual, but hopefully it is enough to get an idea of how easy it is to implement Fluent Validation in your ASP.NET MVC application.

August 19th, 2009 | 18 Comments

One small problem I encountered when getting into Dependency Injection (DI) and Inversion of Control (IoC) was that even though all my services were now beautifully SOLID and test-driven, quite often it was all wasted because I forgot to register them in my IoC container, causing massive errors that wouldn’t be detected until runtime (oops).

Luckily, it is very easy to write a test to check everything has been registered properly. All you need is a bit of reflection to find all the interfaces in an assembly, then try to resolve them all:

[Test]
public void Should_be_able_to_resolve_all_interfaces_in_domain()
{
    var domain = Assembly.GetAssembly(typeof(Book));
    var interfaces = domain.GetTypes().Where(t => t.IsInterface);
    foreach (Type @interface in interfaces)
    {
        Assert.IsNotNull(ServiceLocator.Current.GetInstance(@interface));
    }
}

We can make this even nicer with NUnit 2.5. Instead of a for loop with multiple asserts within one test case (hmm) that can only show one failure at a time (ugh), we can use NUnit parameterized tests to automagically generate a separate test case for each interface we need to resolve:

NUnit parameterized tests

That’s heaps easier to read (otherwise Unity’s exceptions are very terse), and we can see multiple failures in one run. To make NUnit generate this without typing them all out by hand, all you need is the new ValueSource attribute, which lets you choose a method, field or property or method that returns an IEnumerable set of objects:

public IEnumerable<Type> GetDomainInterfaces()
{
    var domain = Assembly.GetAssembly(typeof(Book));
    return domain.GetTypes().Where(t => t.IsInterface);
}

[Test]
public void Should_be_able_to_resolve_domain_service(
    [ValueSource("GetDomainInterfaces")]Type @interface)
{
    Assert.IsNotNull(ServiceLocator.Current.GetInstance(@interface));
}

Note I include this with my integration tests, because it can take a few secs to run (e.g. I keep my NHibernate ISession in the container, and building the session factory takes a long time).

June 8th, 2009 | 2 Comments

Typemock are giving away free licenses of their new ASP.NET Typemock bundle if you blog about it:

Unit Testing ASP.NET? ASP.NET unit testing has never been this easy.

Typemock is launching a new product for ASP.NET developers – the ASP.NET Bundle – and for the launch will be giving out FREE licenses to bloggers and their readers.

The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both Typemock Isolator, a unit test tool and Ivonna, the Isolator add-on for ASP.NET unit testing, for a bargain price.

Typemock Isolator is a leading .NET unit testing tool (C# and VB.NET) for many ‘hard to test’ technologies such as SharePoint, ASP.NET, MVC, WCF, WPF, Silverlight and more. Note that for unit testing Silverlight there is an open source Isolator add-on called SilverUnit.

The first 60 bloggers who will blog this text in their blog and tell us about it, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET dedicated blog, you’ll get a license automatically (even if more than 60 submit) during the first week of this announcement.

Also 8 bloggers will get an additional 2 licenses (each) to give away to their readers / friends.

Go ahead, click the following link for more information on how to get your free license.

This bundle normally costs USD $599, and includes a full version of Typemock Isolator. Definitely a must have if you’re doing TDD with SharePoint.

May 20th, 2009 | No Comments Yet