h1

Automated Testing of Grails domain mapping against a Legacy DB

31 May, 2011

So, its quite normal to develop a Grails application as a greenfield project. You get to let GORM decide how to layout the database, maybe make a few tweaks here and there to improve things when you come to indexing, nothing major. You can be (mostly) sure that it’ll work with the database, as your integration tests will exercise it against the in memory DB, and this translates well to the deployment DB too.

What happens though when you are making an application that is designed to sit on top of an existing database? (the dreaded ‘legacy’…)

This shouldn’t be shied away from, or ignored. It really might not just work out. You have to plan for how to get the app live, and have automatic verification that it will even communicate correctly with the database.

Now, it might not be obvious when you start to use Grails, or hibernate even. You can incorrectly map a domain class to a table, and when the app starts up it will say exactly nothing about the situation. Hibernate does not check that your mappings are correct, it assumes they are. The only indication you will have that something is amiss is when your nice shiny new gui goes bang when some incorrect SQL is generated for you.

This is not something we want.

So, what do we do?

Well, its normal practice to have some kind of semi live environment (read – production like database) that has data in it, for UAT, or load testing, or anything like that.

I’m going to present to you a way to validate that all your Grails domain classes will map correctly to the database, and to do this on your CI server.

So, the basic steps are :-

  • Add a new datasource entry
  • Create a database mapping test
  • Run it in isolation
  • Profit….

DataSource.groovy
Define your datasources, and then include a new entry for your data filled production environment.

DataSource.groovy
 dataSource {
  pooled = true
  driverClassName = "org.hsqldb.jdbcDriver"
  username = "sa"
  password = ""
 }
 hibernate {
  cache.use_second_level_cache = true
  cache.use_query_cache = true
  cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider'
 }
 // environment specific settings
 environments {
  development { ... }
  test { ... }
  uat { ... }
  production { ... }
 }

So, I’ve missed out the JDBC config bits, I’m sure you can figure it out, but we’ve now got a ‘uat’ environment point at your data filled database. We can use this to exercise the DB mappings of all our current a future domain classes.

Next, we need the test

Mapping Test

This is best expressed in code. Make a new integration test (ie test/integration). We need the integration test phase as Grails runs up most of the environment, especially the spring app context and hibernate session factory.

class DatabaseManagementMappingTests extends GrailsUnitTestCase {
 def grailsApplication
@Test
 void domainsMappedCorrectly() {
  def failed = [:]
  grailsApplication.domainClasses.each {
    try {
      it.clazz.list(max:1).each {
        println "${it}"
      }
    } catch (Exception ex) {
      failed[it.clazz] = ex
    }
  }
  if (failed) {
    fail("Domains are not mapped correctly : ${failed.keySet()}")
  }
  }
 }

This queries the grailsApplication for all the domains and then the it.clazz.list(max:1) line will drag back exactly 1 item from each of your domains.

This may or may not load other bits of data via the mappings; assuming that you have data in all the corresponding tables, this will completely and automatically exercise your domain model against a real database.

Run it in isolation

Now, this is no good at all when run via grails test-app as that will simply use the in memory database. If you alter the datasource in use, then we must prevent the other tests running as well otherwise your data filled database is likely to be wiped!

The correct command is

grails -Dgrails.env=uat test-app integration: DatabaseManagementMapping.domainsMappedCorrectly

This switches us to use the UAT datasource, and runs the single integration test specified. There’s a bit of redundancy in there, but I find it makes the intent obvious.

Profit!

At this point you should be able to get your CI server (of any flavour) to run this command and so automatically test your domain class mappings. So after every commit your mappings will be exercised against your database, flagging up schema corruption, typos, migrations not being applied promptly etc.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.