blob: 65b6786eb19786c49f86812a87630e41f26ed77b [file] [log] [blame]
https://docs.spockframework.org[Spock] is the recommended tool for writing unit tests with GORM and is trivial to setup.
==== GORM with Hibernate and Spock Basics
The following is an example Spock unit test:
[source,groovy]
----
import spock.lang.*
import grails.gorm.annotation.Entity
import org.grails.orm.hibernate.HibernateDatastore
class ExampleSpec extends Specification { <1>
@Shared @AutoCleanup HibernateDatastore hibernateDatastore <2>
void setupSpec() {
hibernateDatastore = new HibernateDatastore(Person) <3>
}
void "test something"() { <4>
// your logic here
}
}
@Entity <5>
class Person {
...
}
----
<1> The test should extend `spock.lang.Specification`
<2> The `Shared` annotation is used to indicate to Spock that the `HibernateDatastore` is shared across all tests. The `AutoCleanup` annotation makes sure that `HibernateDatastore` is shutdown when all tests finish executing.
<3> Within the `setupSpec` method a new `HibernateDatastore` is constructed with the classes to use as the argument to the constructor.
<4> You then write your test logic within each method
<5> You can inline domain classes within the unit test if you annotate them with `@Entity`
==== Spock and Transactions
Note that in general you have to wrap your test execution logic in a session or transaction. The easiest way to do this is with `grails.gorm.transactions.Transactional`:
[source,groovy]
----
...
import grails.gorm.transactions.*
import org.springframework.transaction.PlatformTransactionManager
class ExampleSpec extends Specification {
@Shared @AutoCleanup HibernateDatastore hibernateDatastore
@Shared PlatformTransactionManager transactionManager <1>
void setupSpec() {
hibernateDatastore = new HibernateDatastore(Person)
transactionManager = hibernateDatastore.getTransactionManager() <2>
}
@Transactional <3>
def setup() {
new Person(firstName:"Fred").save()
}
@Rollback <4>
void "test execute GORM standalone in a unit test"() {
// your logic here
}
}
----
<1> The `PlatformTransactionManager` is defined as a `Shared` field
<2> You can obtain the `PlatformTransactionManager` from the `HibernateDatastore`
<3> The `Transactional` annotation is used to setup test data
<4> The `Rollback` annotation is used to rollback any changes made within each test
In the example above, each test method is wrapped in a transaction that rolls back any changes using the `grails.gorm.transactions.Rollback` annotation.
TIP: If you want to setup some test data within the `setupSpec` method that is shared across all tests then you can use `withTransaction`:
[source,groovy]
----
...
void setupSpec() {
hibernateDatastore = new HibernateDatastore(Person)
...
Person.withTransaction {
new Person(firstName:"Fred").save()
}
}
----
==== Configuring GORM in Spock
If you need to configure GORM within a Spock unit test you can pass a map to the constructor of `HibernateDatastore`. For example to setup multi-tenancy:
[source,groovy]
----
...
void setupSpec() {
Map configuration = [
'grails.gorm.multiTenancy.mode':'DISCRIMINATOR',
'grails.gorm.multiTenancy.tenantResolverClass':SystemPropertyTenantResolver
]
hibernateDatastore = new HibernateDatastore(configuration, Person)
...
}
----