0
votes

I am new to Grails and learning Grails currently. I configured Mysql as my database. and when I run-app I can see table create in my database.

I tried to do a save() in test case both Unit (extend Specification) and Integration test (extend IntegrationSpec), Test method is shown as follow, which could be passed successfully.

    void "test first save"() {
        when: "when have user id is 'joe', and password is 'secret'"
        def userId = "joe"
        def password = "secret"
        then: "create a user use ${userId} and ${password}"
        User user = new User(userId: userId, password: password, homepage: 'http://www.grailsinaction.com')

        expect: "user can be saved successfully"
        assert user.save(flush:true, failOnError:true)
        assert user.id
        def foundUser = User.get(user.id)
        assert  foundUser?.userId == 'joe'
    }

but I found there are no data inserted into database in both unit and integration test.

I understood that Unit test will only mock the persistence, but integration test should use real database for the testing purpose.

So my question is whether integration should commit data into database? If so, anything could be wrong to make committing not occurred?

1

1 Answers

3
votes

The integration test runner is configured to start a new transaction for every test, and explicitly roll it back at the end of the test. This is convenient because you don't have to do any cleanup work between tests - everything is reset automatically for you. Note that any work done before the tests start (e.g. in BootStrap) will remain for each test since it is committed already, and the rollback resets back to the state at the beginning of each test.

You can disable this for an individual test class by adding

static transactional = false

but I would avoid this except in rare cases where you are testing transaction commits and rollbacks and need full control at that level.

Also note that the Hibernate dbCreate setting will affect things. If you configure data to remain after the tests run but use create-drop, the tables will be dropped at startup and at shutdown, so using create (which only drops at startup) or explicit migrations would be needed to view anything.

FYI - in your test, the line

def foundUser = User.get(user.id)

will not hit the database - Hibernate will simply give you back the instance you just saved. You can see this by turning on SQL logging. If you want to really re-load the object, you need to clear the Hibernate session to force it to issue a query. One easy way to do this is with the withSession method on domain classes (it's independent of the class it's called on, so use any), e.g.

User.withSession { session ->
   session.flush()
   session.clear()
}

I added a flush call to ensure that everything it pushed before clearing.