-
Notifications
You must be signed in to change notification settings - Fork 41
Sample Code
Once you have the plugin installed, it should be as easy as calling build()
on any of your domain objects in your tests.
If you don't pass any parameters to build, it will attempt to provide values for all of the properties that it determines have required values based on the constraints. This includes other domain objects.
If you want to specify particular values, you can pass build a map (just like you can to a domain object constructor). The plugin will attempt to create new values for any required properties that you don't specify in the map.
domainObject.build(myProperty:'myPropertyValue')
The build method default is to attempt to save the populated domain object. You can avoid saving the object first by calling the buildWithoutSave method:
domainObject.buildWithoutSave(myProperty:'myPropertyValue')
If you want to try testing the build plugin on all of your domain objects to see if it'll work out of the box for you, you can create an integration test to exercise the plugin:
grails create-integration-test TestData
And putting these contents in the new test/integration/TestDataTests.groovy
file:
def grailsApplication // get grails app injected into test
void testBuildAllDomains() {
def successful = true
grailsApplication.domainClasses.each { domainClass ->
println "Test of ${domainClass.name}.build()"
try {
def domainObject = domainClass.clazz.build()
assertNotNull domainObject."${domainClass.identifier.name}"
println "********** SUCCESSFUL BUILD OF $domainClass"
} catch (Exception e) {
println "********** FAILED BUILD OF $domainClass"
successful = false
}
}
assert successful
}
There currently isn't built-in support for uniqueness constraints, but it's pretty easy to get this working using a closure in the config file to generate a series of unique values.
testDataConfig {
sampleData {
'com.foo.Book' {
def i = 1
title = {-> "title${i++}" } // creates "title1", "title2", ...."titleN"
}
}
}
If your test cares about this unique value, you'll likely want to reset the configuration either directly in your test or in the setUp of the test. Otherwise, other tests could have grabbed the value that you were expecting. To reset the configuration back to the original state, use this:
grails.buildtestdata.TestDataConfigurationHolder.reset()
When you have a parent object that you want to have specific child objects, here's one way this can be done.
class Issue {
String title
static hasMany = [pages: Page]
}
class Page {
Integer number
static hasMany = [advertisments: Advertisment]
static belongsTo = [issue: Issue]
}
You can create an issue and then give it pages:
// build the issue first
def issue = Issue.build()
(1..5).collect { Page.build(issue: issue, number: it) }
assertEquals 5, issue.pages.size() // pages are automatically added to the issue's hasMany pages collection
assertEquals 1, Issue.list().size() // don't build extra issues when building pages
We don't want to build the Page objects before we have the Issue otherwise the build method will create dummy issues in the database for each page (and that last assert would fail).
Having build assign system wide default property values, or give values to classes that are "distant" in the object graph from the object you're building can all be done with the TestDataConfig configuration file.
If you want to see the detail of what objects the plugin is trying to save, you can set the logging level for the DomainTestDataService and the DomainInstanceBuilder to info. Just stick this line in your 'logback.groovy'
logger("grails.buildtestdata.DomainInstanceBuilder", INFO)
If you want to see all of the gory detail about what the plugin is doing as it traverses the object graph and examines each property, set the logging level to debug and add in the property handlers:
logger("grails.buildtestdata", DEBUG)