Antonio
Antonio

Reputation: 181

Grails testing a Factory class

Given that I'm newbie regarding grails, I'm trying to test a factory class. The Factory class is in the src folder since I don't want it as a service.

class UserFactory {

static Map userDefaults = [
        email           : '[email protected]',
        alias           : 'myalias',
        firstName       : 'Antonio',
        lastName        : 'Roma',
        password        : 'asdhjs',
        placeOfBirth    : 'Milan',
        placeOfResidence: 'Berlin',
        dateOfBirth     : new Date() - 4000
]

static User build(Map properties, Map options = [persisted: true]) {
    userDefaults.putAll properties
    def user = new User(userDefaults)

    if (options.persisted) { user.save() }

    return user
}

static Collection<User> build(Collection<Map> properties, Map options = [persisted: true]) {
    properties.collect { build(it, options) }
}

}

I want to test if the users are created and stored properly through GORM. Here the integration test:

@TestMixin(DomainClassUnitTestMixin)
class UserFactoryIntegrationSpec extends Specification {

def setup() {
    mockDomain(User)
}

def cleanup() {
}

void "create user"() {
    when:
    User user = UserFactory.build([alias: 'xx', email: '[email protected]'])

    then:
    User.count() == 1
    user.alias == 'xx'
    user.email == '[email protected]'
    user.id != null
}

void "create users"() {
    when:
    Collection<User> users = UserFactory.build([[alias: 'xx', email: '[email protected]'], [alias: 'yy', email: '[email protected]']])

    then:
    users.size() == 2
    users.alias == ['xx', 'yy']
    users.email == ['[email protected]','[email protected]']
    users.id != [null, null]
}

}

The users are not stored, I guess GORM is not loaded correctly... am I missing some annotations?! here the results of test-app integration: UserFactoryIntegrationSpec

User.count() == 1
     |       |
     0       false

users.id != [null, null]
|     |  |
|     |  false
|     [null, null]
[rigel.resources.User : (unsaved), rigel.resources.User : (unsaved)]

Upvotes: 0

Views: 88

Answers (1)

Burt Beckwith
Burt Beckwith

Reputation: 75681

You started on such a high note:

I want to test if the users are created and stored properly through GORM. Here the integration test:

but then it all went kablooey because you're using a unit test pretending to be an integration test, and worse than that, you're testing persistence with unit tests.

Do use integration tests to test persistence. Only use domain class mocking when a unit test makes sense for what you're testing, and you want to force the domain tier to respond a certain way so you can focus on the controller/service/etc. that's being tested.

Use integration tests which configure at the bare minimum an H2 database, with full ACID support, row locking, real SQL queries, etc. And if you prefer you can switch it out for a test Oracle schema, MySQL database, whatever. But your tests run real queries and updates. If you use mocks to test persistence, you're really just testing the mocks.

Integration tests don't use mixins, mocks, etc. There's a real Spring ApplicationContext, Hibernate (or whatever GORM you're using), plugins are loaded, etc. Use JUnit 3 (extend GroovyTestCase), or JUnit 4 (no base class, using JUnit annotations) or Spock. Note that integration tests configure each test run to happen in a transaction, and that's rolled back at the end of a successful test or earlier if the test fail, but in either case there's no carryover between tests.

If you want to use Spock (and you should) then extend grails.test.spock.IntegrationSpec for newer versions of Grails that default to Spock tests. In older versions, install the spock plugin and use the plugin's integration base class.

Upvotes: 2

Related Questions