4
votes

I have a controller that uses a command object in a controller action. When mocking this command object in a grails' controller unit test, the hasErrors() method always returns false, even when I am purposefully violating its constraints. The more baffling thing is that in production, hasErrors() works! So this is just a testing problem.

 def save = { RegistrationForm form ->
  if(form.hasErrors()) {
   // code block never gets executed
  } else {
   // code block always gets executed
  }
 }

In the test itself, I do this:

 mockCommandObject(RegistrationForm)
 def form = new RegistrationForm(emailAddress: "ken.bad@gmail",
  password: "secret", confirmPassword: "wrong")

 controller.save(form)

I am purposefully giving it a bad email address, and I am making sure the password and the confirmPassword properties are different. In this case, hasErrors() should return true... but it doesn't. I don't know how my testing can be any where reliable if such a basic thing does not work :/

Here is the RegistrationForm class, so you can see the constraints I am using:

class RegistrationForm {
 def springSecurityService

 String emailAddress
 String password
 String confirmPassword

 String getEncryptedPassword() {
  springSecurityService.encodePassword(password)
 }

 static constraints = {
  emailAddress(blank: false, email: true)
  password(blank: false, minSize:4, maxSize: 10)
  confirmPassword(blank: false, validator: { confirmPassword, form ->
   confirmPassword == form.password
  })
 }
}
1
I got it work. I had to call form.validate() before I passed the "form" object into the action under test. As a side-note... are you kidding me?! Seriously... in the framework itself, it calls validate automatically... but I have to do that in my test-case? Can't this just work like it would in production? Man, exception to the rule after exception to the rule just to get this to work. ARG! Testing in Grails sucks. It is bad. It is easier to do in raw Spring. - egervari
I had the same problem and I were calling validate as You posted in your comment but then found better way. Put in your setUp() mockCommandObject RegistrationForm and then: RegistrationForm .metaClass.hasErrors(){ !delegate.validate() } and in tear down: GroovySystem.metaClassRegistry.removeMetaClass RegistrationForm. - jjczopek

1 Answers

1
votes

Have you tried mockForConstraintsTests ?

E.g. something like...

void testSomething() {

    mockForConstraintsTests(RegistrationForm)

    def form = new RegistrationForm(emailAddress: "ken.bad@gmail", password: "secret", confirmPassword: "wrong")

    form.validate()

    assert 1 == form.errors.getErrorCount()
}

Try just testing the RegistrationForm command object first in its own unit test. (gain some confidence that its actually working)

Maybe using the above for the basis of your test will help!?!?