views:

39

answers:

2

I'm learning grails from Grails - getting started by Jason Rudolph book. My domain class looks like that:

class Race {

  String name;
  Date startDateTime
  String city
  String state
  Float distance
  Float cost
  Integer maxRunners = 10000

  static hasMany = [registrations: Registration]

  static constraints = {
    name(maxSize: 50, blank: false)
    startDateTime(validator: {
      return it > new Date()
    })
    city(maxSize: 30, blank: false)
    state(inList: ['GA', 'NC', 'SC', 'VA'], blank: false)
    distance(min: 3.1f, max: 100f)
    cost(min: 0f, max: 999.99f)
  }

  String toString() { "${this.name} : ${this.city}, ${this.state}" }
}

I want to test the custom validation of startDateTime field. Test looks like that:

class RaceTests extends GrailsUnitTestCase {
  protected void setUp() {
    super.setUp()
  }

  protected void tearDown() {
    super.tearDown()
  }

  void testCustomDateValidation() {
    def race = new Race()
    race.startDateTime = null
    assertFalse(race.validate())
  }
}

Test looks similar to the one from book I mentioned earlier. But I'm getting

groovy.lang.MissingMethodException: No signature of method: racetrack.Race.validate() is applicable for argument types: () values: []

I'm stuck and didn't find any solution :/ Any help will be appreciated.

+1  A: 

You're missing the mockForConstraintsTests() call. The common pattern is to do this in setUp()

protected void setUp() {
  super.setUp()
  mockForConstraintsTests(Race)    
}

For details: http://mrhaki.blogspot.com/2009/04/unit-testing-constraints-in-domain.html

Stefan
+2  A: 

You should not use unit tests or mocking to test domain classes. Grails does create a unit test for domain classes and this should be changed. Move the class to the same package and folder under test/integration and change the base class to GroovyTestCase and you'll have a proper test that runs with the in-memory database and tests persistence, not the mocking framework.

Burt Beckwith
I assume the rationale is that mocking does not provide the same behaviour than the real DB. The downside is unit tests run much more faster than integration test. For TDD integration tests are IMHO too slow. So I'll stick with unit testing here.
Stefan