Having used fixtures to configure test data within in other frameworks I thought I’d use the Grails Fixtures plugin for my latest Grails project. It may have simply been a bad-day-at-the-office but for whatever reason, this took me much longer than it probably should have! Having finally managed to piece everything together using the documentation at:
- http://www.grails.org/Fixtures+Plug
- http://www.keithnordstrom.com/post/2010/01/11/Grails-Fixtures-Plugin-PrePost-processing.aspx
- http://jira.codehaus.org/browse/GRAILSPLUGINS-830?page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel
The two key points I originally missed from the documentation were:
- Fixture files are .groovy files (rather than .dat, .txt etc.) because they contain closures. And, the .groovy extension is not included on the fixtureLoader.load() call. If the file is not found, the fixtures plugin will give a “pattern” error. The default root path for fixtures is “/fixtures”.
- The object classes need to be fully-qualified even if the calling class (BootStrap.groovy) has imported them. The fixtures plugin error messages will provide details of these within a parse error.
Here is a summary of my final code in case anyone else finds themselves struggling with this. This code does the following:
- Creates and persists a Spring Security Role.
- Defines an Organisation fixture.
- Defines a Person fixture belonging to the organisation above.
- Defines a User fixture for the person above, giving them a username and encrypted password.
- Assigns the User to the Role defined in step 1.
The two main files are involved are:
- /grails-app/conf/BootStrap.groovy
- /fixtures/myfixtures.groovy (Fixture files require the .groovy extension. Potentially, there should be separate fixture files for Organisation, Person and User.)
The steps involved are:
Step 1: Install and configure the Spring Security Plugin
Step 2: Install and configure the Build Test Data Plugin
The Build Test data Plugin automatically creates beans which satisfy the constraints on domain objects but still allow fields to be specified. Using this plugin to create fixtures helps to protect the fixtures from breaking when fields are added to domain objects in the future.
Step 3: Install the Grails fixtures plugin: grails install-plugin fixtures
Step 4: Edit BootStrap.groovy:
import com.myco.organisation.Organisation
import com.myco.organisation.Person
import com.myco.auth.Role
import com.myco.auth.User
import com.myco.auth.UserRole
import grails.util.GrailsUtil
import org.codehaus.groovy.grails.commons.GrailsApplication
class BootStrap {
def springSecurityService // autowired by Spring Security plugin
def fixtureLoader // autowired by Fixtures plugin
def init = { servletContext ->
boolean isProd = GrailsUtil.environment == GrailsApplication.ENV_PRODUCTION
// Create fixtures for non-production environment. E.g. Test and development.
if (!isProd) {
fixtureLoader.load('myfixtures') // Ommit the .groovy extension!
assert Organisation.count() == 1
assert Person.count() == 1
assert User.count() == 1
assert UserRole.count() == 1
}
}
def destroy = {
}
}
Step 5: Edit /fixtures/myfixtures.groovy
// NOTE 1: fully-qualified class names are required!
// NOTE 2: using "build-test-data" plugin building function for future flexibility
pre {
// Expose a role for the fixture and post closures
carrierRole = com.myco.auth.Role.findByAuthority('ROLE_ORGANISATION_ADMIN')
}
fixture {
organisation1 = com.myco.organisation.Organisation.build(name:"Some Organisation")
johnsmith = com.myco.organisation.Person.build(firstName:"John",lastName:"Smith",organisation: organisation1)
user = com.myco.auth.User.build(person:johnsmith, username:"jsmith", password:springSecurityService.encodePassword('mypassword'), enabled: true)
}
post {
// Assign a role to the user and flush the data to the database.
com.myco.auth.UserRole.create(user, carrierRole, true)
}
Step 6: Create a functional test (in this case /selenium/FixtureTests.groovy )
import com.myco.organisation.Person
import grails.plugins.selenium.SeleniumAware
import groovy.util.GroovyTestCase;
@Mixin(SeleniumAware)
class FixtureTests extends GroovyTestCase {
void setUp() {
}
void testLoad() {
def p = Person.findByFirstName("John")
assertNotNull p
assertEquals "Smith", p.lastName
}
}

