Grails, good to know: Working with the Build Test Data Plugin

von Tobias Kraft

Grails

There are several choices for creating test data when working with Grails. Beside the manual creation of domain objects it is possible to use one of the existing plugins. Before Grails 3.0 one of the good choices was the Fixture Plugin for specifying domain test data. This plugin is not ported to newer Grails versions and therefore no longer an option. Another good choice is the Build Test Data Plugin which is in the focus of this post. 

After referencing the plugin via the build.gradle file, new domain objects can be created easily by calling the build()method on a domain class. The following listing demonstrates the usage by creating two new entities of the type project. All required attributes of the entities are populated automatically or can be alternatively specified explicitly as shown for the second entity.

def "Create project"() {
    expect: "the database is empty"
        Project.count() == 0
    when: "store two projects"
        Project.build()
        Project.build(name: "The first project")
    then: "two projects exists"
        Project.count() == 2
}

The documentation provides more information on the general usage of the plugin. The following sections provide two best practices on using some less known features of the Build Test Data Plugin.

Testing REST APIs

Nowadays many Grails applications provide REST APIs that have also run through the automatic test cycles. Assuming in our case that an existing project from an external system should be imported via REST, it is necessary for a test to construct a post request that contains all necessary attributes and especially an ID. When calling the standard build()method on the project entity and then converting it to JSON, the object will already be saved in the database before sending it via REST to the application. This can be avoided by calling the buildWithoutSave() method instead of the build() method. An example for the usage is shown in the following code snippet:

def "trigger import of new project from external system"() {
    given: "prepare project"
        Project project = Project.buildWithoutSave()
    when: "new project is send for importing"
        // wrapper for converting entity to JSON object and sending the request
        Map r = sendRequestToAction("POST", null, project, "import/project", authToken)
    then: "status code is OK"
        r.responseCode == OK
}

Creation of custom identities

The ID of the entity is available after creating a new entity via the build() method, when using the standard settings for domain classes. Depending on the requirements it might be necessary to use custom IDs for the database that are assigned manually. This can be specified in the mapping block of a domain class, as shown below:

static mapping = {
    id generator: 'assigned'
}

To avoid the manual assignment of IDs in test cases it is possible to enhance the TestDataConfig file. This file of the BuildTestData Plugin can be used to define static or dynamic values for the attributes of entities when creating test data. In our case we assume that UUIDs are assigned as IDs to the domain classes. We want to make sure that an artificial ascending UUID is assigned to every created entity. This can be done by defining a closure that generates the assignment code of an ID for each domain class which is shown in the following listing.

testDataConfig {
    sampleData {
        // iterate through all domain classes
        Holders.grailsApplication.domainClasses.each { domainClass ->
            this."${domainClass.fullName}" {
                this."${GormHelper.getIdentifierForDomain(domainClass.clazz)}" = {
                    GormHelper.getUUIDForTest()
                }
            }
        }
    }

    // The following result will be generated:
    //    testDataConfig {
    //        sampleData {
    //            'de.exensio.Project' {
    //                id = GormHelper.getUUIDForTest()
    //            }
    //            'de.exensio.Task' {
    //                id = GormHelper.getUUIDForTest()
    //            }
    //            ...
    //        }
    //    }
}

A simple test for verifying the creation of project entities and its correct UUID assignment can look like shown below.

def "Validate projects"() {
    when: "create two projects"
        Project.build(name: "New grails project")
        Project.build(name: "Legacy project")
    then: "two projects exists"
        Project.count() == 2
    and: "the identifier is a valid UUID"
        Project.list().every {
            it.id =~ /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
        }
}

Kategorien: GrailsSpockTesting

Zurück