Home > Uncategorized > Fakes Arent Object Mothers Or Test Builders

Fakes Arent Object Mothers Or Test Builders

November 20th, 2008 Leave a comment Go to comments

Fakes are not Object Mothers or Test Data Builders and Extensions are a bridge to aid BDD through StoryQ

I’ve just spent the week at Agile2008 and have had it pointed out to me that I have been using Fakes as nomenclature when in fact it is an Object Mother pattern. So I have set off to learn about the Object Mother pattern and in doing so came across the Test Data Builder pattern. But because I am currently working in C# 3.5 and using PI/POCOs/DDD, the builder pattern at looking a little heavy and the criticism of Object Mother holds that it ends up as a God object and hence a little too cluttered.

I’ve also found utilising Extensions in C# 3.5 as a good way to keep the OM clean. By adding extensions, it cleans up the code significantly such that BDD through StoryQ became attractive. Extensions have these advantages:

  • Allows you to put a SetUp (Build/Contruct) method on the object itself
  • Makes this/these methods only available within the test project only
  • Keeps data/values separate from setup ie as a cross-cutting concern
  • In tests, specific edge data – or basic tests – aren’t put into object mothers
  • Extensions end up concise and DRY code

Background

I have been using a Fake models as a strategy to unit test (based on Jimmy Nillson’s DDD in C# book). Technically, these are not fakes. According to sites, fakes are a strategy to replace service objects rather than value objects. My use of fakes is rather the “Object Mother” pattern. (Am I the only person six years behind? Probably.) Since knowing about this pattern, I’ve found it on Fowler’s bliki and the original description at XP Universe 2001 (however, I haven’t been able to download the paper as yet – xpuniverse.com isn’t responding).

Having read entries around this pattern, another pattern emerged: the “Test Data Builder” pattern. It is a likable pattern. (In fact, it could be leveraged as an internal DSL - but I haven’t pursued that as yet.) But, given the work I do in C#, it looks a little heavy as it is useful to cope with complex dependencies. In contrast, the fake/object mother I have been using has been really easily to teach, and well liked by, developers.

Basic approach

To test these approaches, I am going to create a simple model: User which has an Address. Both models have validations on the fields and I can ask the model to validate itself. You’ll note that I am using Castle’s validations component. This breaks POCO rules of a single library but in practice is a good trade-off. My basic test heuristic:

  • populate with defaults = valid
  • test each field with an invalid value
  • ensure that inherited objects are also validated

Four Strategies:

  1. Object Mother
  2. Test Data Builder
  3. Extensions with Object Mother
  4. StoryQ with Extensions (and Object Mother)

Strategy One: Object Mother

First, the test loads up a valid user through a static method (or property if you wish). I use the convention “Valid” to always provide back what is always a valid model. This is a good way to demonstrate to new devs what the exemplar object looks like. Interesting, in C# 3.5, the new constructor convention works very well here. You can read down the list of properties easily, often without need to look at the original model code. Moreover, in the original object, there is no need for an overloaded constructor.

[Test]
 public void ValidUser()
 {
     var fake = TestUser.Valid();
     Assert.IsTrue(fake.IsOKToAccept());
 }

  public class TestUser
   {
       public static User Valid()
       {
           return new User {
               Name = "Hone", 
               Email = "Hone@somewhere.com", 
               Password="Hone", 
               Confirm = "Hone"
       }
   }

Oh, and here’s the User model if you are interested. Goto to Castle Validations if this isn’t clear.

 public class User
 {
     [ValidateLength(1, 4)]
     public string Name { get; set; }

     [ValidateEmail]
     public string Email { get; set; }

     [ValidateSameAs("Confirm")]
     [ValidateLength(1,9)]
     public string Password { get; set; }
     public string Confirm { get; set; }

     public bool IsOKToAccept()
     {
         ValidatorRunner runner = new ValidatorRunner(new CachedValidationRegistry());
         return runner.IsValid(this);
     }
  }

Second, the test works through confirming that each validation works. Here we need to work through each of the fields checking for invalid values. With the object mother pattern, each case is a separate static method: email, name and password. The strategy is to always always start with the valid model, make only one change and test. It’s a simple strategy, easy to read and avoids duplication. The problem with this approach is hiding test data; we have to trust that the method, “invalidName”, is actually an invalid name or follow it through to the static method. In practice, it works well enough and avoids duplication.

public static User InvalidEmail()
{
    var fake = Valid();
    fake.Email = "invalid@@some.com";
    return fake;
}

public static User InvalidName()
{
    var fake = Valid();
    fake.Name = "with_more_than_four";
    return fake;
}

public static User InvalidPassword()
{
    var fake = Valid();
    fake.Password = "not_same";
    fake.Confirm = "different";
    return fake;
}

[Test]
public void InValidEmail()
{
    var fake = TestUser.InvalidEmail();
    Assert.IsFalse(fake.IsOKToAccept());
}

[Test]
public void InValidName()
{
    var fake = TestUser.InvalidName();
    Assert.IsFalse(fake.IsOKToAccept());
}

[Test]
public void InValidPassword()
{
    var fake = TestUser.InvalidPassword();
    Assert.IsFalse(fake.IsOKToAccept());
}

Strategy Two: Test Data Builder

I’m not going to spend long on this piece of code because the builder looks like too much work. The pattern is well documented so I assume you already understand it. I do think that it could be useful if you want to create an internal DSL to work through dependencies. Put differently, this example is too simple to demonstrate a case for when to use this pattern (IMHO).

First, here’s the test for the valid user. I found that I injected the valid user behind the scenes (with an object mother) so that I could have a fluent interface with Build(). I can overload the constructor to explicitly inject a user too. I have two options when passing in an object: (1) inject my object mother or (2) inject a locally constructed object. The local construction is useful for explicitly seeing what is being tested. But really, it is the syntactic sugar of C# that is giving visibility rather than the pattern; so, for simple cases, the syntax of the language renders the pattern more verbose.

[Test]
public void ValidUser()
{
    var fake = new UserBuilder().Build();
    Assert.IsTrue(fake.IsOKToAccept());

}

[Test]
public void LocalUser()
{
    var fake = new UserBuilder(TestUser.Valid()).Build();
    Assert.IsTrue(fake.IsOKToAccept());

    fake = new UserBuilder(new User
                    {
                        Name = "Hone", 
                        Email = "good@com.com",
                        Password = "password",
                        Confirm = "password",
                        Address = new Address
                                      {
                                          Street = "Fred",
                                          Number = "19"
                                      }
                    })
                    .Build();
    Assert.IsTrue(fake.IsOKToAccept());
}

public class UserBuilder
{
    private readonly User user;

    public UserBuilder()
    {
        user = TestUser.Valid();
    }

    public UserBuilder(User user)
    {
        this.user = user;
    }

    public User Build() { return user; }
}

Second, let’s validate each field. In the code, and on the positive side, it is clear what constitutes an invalid value and it caters for dependencies such as in “withPassword” between password and confirm. But, really, there is just too much typing; I have to create a method for every field and dependency. For simple models, I am not going to do this. For complex or large models, it would take ages.

[Test]
public void InValidEmail()
{
    var fake = new UserBuilder()
        .withEmail("incorect@@@emai.comc.com.com")
        .Build();
    Assert.IsFalse(fake.IsOKToAccept());
}

[Test]
public void InValidName()
{
    var fake = new UserBuilder()
        .withName("a_name_longer_than_four_characters")
        .Build();
    Assert.IsFalse(fake.IsOKToAccept());
}

[Test]
public void InValidPassword()
{
    var fake = new UserBuilder()
        .withPassword("bad_password")
        .Build();
    Assert.IsFalse(fake.IsOKToAccept());
}

public class UserBuilder
{
    private readonly User user;

    public UserBuilder()
    {
        user = TestUser.Valid();
    }

    public UserBuilder(User user)
    {
        this.user = user;
    }

    public UserBuilder withEmail(string email)
    {
        user.Email = email;
        return this;
    }

    public UserBuilder withPassword(string password)
    {
        user.Confirm = password;
        user.Password = password;
        return this;
    }

    public UserBuilder withName(string name)
    {
        user.Name = name;
        return this;
    }

    public UserBuilder withAddress(Address address)
    {
        user.Address = address;
        return this;
    }

    public User Build() { return user; }
}

Strategy Three: Object Mother with Extensions

Having tried the two previous patterns, I now turn to what extensions have to offer me. (Extensions are something I have been meaning to try for a while.) As it turns out extensions combined with the new constructors allow for SOC and DRY and also allow us to separate valid and invalid data in tests. There is a downside of course. It requires some (reflection) code to make it play nicely. More code – a slippery slope some might say …

First, I have added a new method to my User model in the form of an extension. I have named it SetUp so that it translates into the setup and teardown (init and dispose) phases of unit testing. I could use Build or Construct instead. This method returns my object mother. I still like to keep my object mother data separate because I think of construction and data as separate concerns.

[Test]
 public void ValidUser()
 {
     var fake = new User().SetUp();
     Assert.IsTrue(fake.IsOKToAccept());
 }

 public static User SetUp(this User user)
 {
     User fake = TestUser.Valid();
     return fake; 
 }

I also want to test how to create a version of the user visible from the test code. This is where more code is required to combine the any provided fields from the test with the default, valid model. In returning hydrated test user, this method accepts your partially hydrated object and then adds defaults. The goal is that your unit test code only provides specifics for the test. The rest of the valid fields are opaque to your test; the code reflects on your model only hydrating empty fields so that validations do not fail. This reflection code is used by all SetUp methods across models.

[Test]
 public void LocalUser()
 {
     var fake = new User { Name = "John", Email = "valid@someone.com" }.SetUp();
     Assert.IsTrue(fake.IsOKToAccept());
 }

 public static User SetUp(this User user)
 {
     User fake = TestUser.Valid();
     SyncPropertiesWithDefaults(user, fake);
     return fake; 
 }

 private static void SyncPropertiesWithDefaults(object obj, object @base)
   {
       foreach (PropertyInfo prop in obj.GetType().GetProperties())
       {
           object[] val = new object[1];
           val[0] = obj.GetType().GetProperty(prop.Name).GetValue(obj, null);
           if (val[0] != null)
           {
               obj.GetType().InvokeMember(prop.Name, BindingFlags.SetProperty, Type.DefaultBinder, @base, val);
           }
       }
   }

Second, let’s again look at the code to validate all the fields. Now, note at this point there no other object mothers. I see this strategy says, use object mothers to model significant data and avoid cluttering these with edge cases. The result is to hand in the field/value to isolate and then test. I find this readable and it addresses the concern of not making visible the edge case (invalid) data.

[Test]
public void InValidEmail()
{
    var fake = new User { Email = "BAD@@someone.com" }.SetUp();
    Assert.IsFalse(fake.IsOKToAccept());
}

[Test]
public void InValidName()
{
    var fake = new User { Name = "too_long_a_name" }.SetUp();
    Assert.IsFalse(fake.IsOKToAccept());
}

[Test]
public void InValidPassword()
{
    var fake = new User { Password = "password_one", Confirm = "password_two" }.SetUp();
    Assert.IsFalse(fake.IsOKToAccept());
}

Using extensions combined with constructors are nice. We can also format the page to make it look like a fluent interface if need. For example:

[Test]
public void InValidPassword()
{
    var fake = new User 
                { 
                    Password = "password_one", 
                    Confirm = "password_two" 
                }
                .SetUp();
    Assert.IsFalse(fake.IsOKToAccept());
}

Strategy Four: BDD and StoryQ

Having worked out that using extensions reduce repetitious code, I still think there is a smell here. Are those edge cases going to add value in the current form? They really are bland. Sure, the code is tested. But, really, who wants to read and review those tests? I certainly didn’t use them to develop the model code; they merely assert overtime that my assumptions haven’t changed. Let’s look at how I would have written the same tests using BDD and in particularly StoryQ. Here’s a potential usage of my User model.

Story: Creating and maintaining users

  As an user
  I want to have an account
  So that I can register, login and return to the site

  Scenario 1: Registration Page
    Given I enter my name, address, email and password     
    When username isn't longer than 4 characters           
      And email is validate                                
      And password is correct length and matches confirm   
      And address is valid                                 
    Then I can log now login
      And I am sent a confirmation email

Leaving aside any problems in the workflow (which there are), the story works with the model in context. Here is the code that generates this story:

[Test]
public void Users()
{
    Story story = new Story("Creating and maintaining users");

    story.AsA("user")
        .IWant("to have an account")
        .SoThat("I can register, login and return to the site");

    story.WithScenario("Registration Page")
        .Given(Narrative.Exec("I enter my name, address, email and password", 
                 () => Assert.IsTrue(new User().SetUp().IsOKToAccept())))
        
        .When(Narrative.Exec("username isn't longer than 4 characters", 
                 () => Assert.IsFalse(new User{Name = "Too_long"}.SetUp().IsOKToAccept())))

        .And(Narrative.Exec("email is validate", 
                 () => Assert.IsFalse(new User { Email = "bad_email" }.SetUp().IsOKToAccept())))

        .And(Narrative.Exec("password is correct length and matches confirm", 
                 () => Assert.IsFalse(new User { Password = "one_version", Confirm = "differnt"}.SetUp().IsOKToAccept())))

        .And(Narrative.Exec("address is valid", 
                  () => Assert.IsFalse(new User { Address = new Address{Street = null}}.SetUp().IsOKToAccept())))
        
        .Then(Narrative.Text("I can log now login"))
        .And(Narrative.Text("I am sent a confirmation email"));

    story.Assert();
}

Working with BDD around domain models and validations makes sense to me. I think that it is a good way to report validations back up to the client and the team. There is also a good delineation between the “valid” model (“Given” section) and “invalid” (“When” section) edge cases in the structure. In this case, it also demonstrates that those models so far do nothing because there are no tests in the “Then” section.

Some quick conclusions

  1. Syntactic sugar of new constructor methods in C# 3.5 avoids the need for “with” methods found the Test Data Builder pattern
  2. Extensions may better replace the Build method in the builder
  3. Object mothers are still helpful to retain separation of concerns (eg data from construction)
  4. Go BDD ;-)

Well that’s about it for now. Here’s a download of the full code sample in VS2008.

Postscript: About Naming Conventions

How do I go about naming my object mother? I have lots of options: Test, Fake, ObjectMother, OM, Dummy. Of course, if I was purist it would be ObjectMother. But that doesn’t sit well with me when explaining it others. Although it does make explicit the pattern being used, I find fake most useful (eg FakeUser). It rolls off the tongue, it is self evident enough to outsiders as a strategy. Test (eg TestUser), on the other hand, is generic enough that I have to remind myself of its purpose and then I find I always need to do quick translations from the tests themselves. For example, with UserTest and TestUser I have read them to check which I am working with. For these samples, I have used TestUser. If you come back to my production code you will find FakeUser. I hope that doesn’t prove problematic in the long run as it isn’t really a fake.