Chapter 4. Writing Fixtures in Groovy

Abstract

We can take advantage of one of Groovy's features to reduce the boilerplate when writing fixtures. This chapter explains how.

One of the classes provided by the Groovy runtime is ObjectGraphBuilder, which (as per its documentation) is "a builder for an arbitrary graph of beans that follow the JavaBean convention,... useful for creating test data for example". Which is, indeed, exactly what we need to do when we create fixtures for use with the in-memory object store.

The Groovy Objects applib extends this class by providing the DomainObjectBuilder, which additionally ensures that domain objects are instantiated through the DomainObjectContainer. The original ObjectGraphBuilder also needs to be told explicitly where the domain object packages are, so DomainObjectBuilder makes this easy to do in a typesafe way.

Let's see it in action. Here's the fixture from the Groovy Objects testapp, to create 3 Employees, some Claims and some ClaimItems within those Claims:

class ClaimsFixture extends AbstractFixture {

    @Override
    public void install() {
        def builder = new DomainObjectBuilder(getContainer(), Employee.class, Claim.class)

        builder.employee(id: 'fred', name:"Fred Smith")
        builder.employee(id: "tom", name: "Tom Brown") {
            approver( refId: 'fred')
        }
        builder.employee(name: "Sam Jones") {
            approver( refId: 'fred')
        }

        builder.claim(id: 'tom:1', date: days(-16), description: "Meeting with client") {
            claimant( refId: 'tom')
            claimItem( dateIncurred: days(-16), amount: money(38.50), description: "Lunch with client")
            claimItem( dateIncurred: days(-16), amount: money(16.50), description: "Euston - Mayfair (return)")
        }
        builder.claim(id: 'tom:2', date: days(-18), description: "Meeting in city office") {
            claimant( refId: 'tom')
            claimItem( dateIncurred: days(-18), amount: money(18.00), description: "Car parking")
            claimItem( dateIncurred: days(-18), amount: money(26.50), description: "Reading - London (return)")
        }
        builder.claim(id: 'fred:1', date: days(-14), description: "Meeting at clients") {
            claimant( refId: 'fred')
            claimItem( dateIncurred: days(-14), amount: money(18.00), description: "Car parking")
            claimItem( dateIncurred: days(-14), amount: money(26.50), description: "Reading - London (return)")
        }
    }

    private Date days(int days) {
        Date date = new Date();
        date = date.add(0,0, days);
        return date
    }

    private Money money(double amount) {
        return new Money(amount, "USD");
    }
}

The builder is instantiated by passing in the DomainObjectContainer, as well as one representative class from each package that holds entities to be built. In this case the Employee.class takes care of the employee package (for just Employee itself), while Claim.class represents the claims package (for both Claim and ClaimItem).

The DSL for building the object graph is just that defined by Groovy's ObjectGraphBuilder. To my eyes at least, this is easier to follow than its Java equivalent.

There is one limitation to be aware of, though, which relates to how the Claim/ClaimItem parent/child is wired up. It's important for the collection name in the parent (Claim) to match that of the class name of the child (ClaimItem), and the back reference in the child (if there is one) to match the class name of the parent. For the test app, this means that the collection in Claim is called claimItems. If this is irksome, then the ObjectGraphBuilder does define the ability to tweak its behaviour as to how the relationship name is inferred. (A future enhancement to Groovy Objects might be to solve this problem in the general case, by perform the wiring using the Naked Objects metamodel).