3

I have used manually written as well as Grails generated Unit tests for this command object:

   package myapp

    @grails.validation.Validateable
    class SearchCommand {
       String basisBuild
       String buildToSearch

       static constraints = {
          basisBuild(blank: false)
       }
    }

After having my hand written unit test fail I used Grails:

create-unit-test  myapp.SearchCommand

I filled in the Unit Test, and made an assertion that should pass per documentation on mocked constraints:

package myapp
import static org.junit.Assert.*

import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*

@TestMixin(GrailsUnitTestMixin)
class SearchCommandTests {

    void setUp() {
        mockForConstraintsTests(SearchCommand)
    }

    void tearDown() {
        // Tear down logic here
    }

    void testSomething() {
        SearchCommand commandUnderTest = new SearchCommand()

        commandUnderTest.validate(basisBuild: "")

        assertEquals "blank", commandUnderTest.errors['basisBuild']
    }
}

Why am I getting this failure?

grails> test-app
| Running 9 unit tests... 9 of 9
| Failure:  testSomething(com.siemens.soarian.sf.gap.SearchCommandTests)
|  java.lang.AssertionError: expected:<blank> but was:<null>
        at org.junit.Assert.fail(Assert.java:93)
fergjo
  • 63
  • 2
  • 8

3 Answers3

5

I believe I found the grails supported way to unit test Command objects in grails 2.0. You need to use mockCommandObject provided by the ControllerUnitTestMixin.

Credit to Erik

http://www.jworks.nl/2012/04/12/testing-command-objects-in-grails-2-0/

Perulish8
  • 223
  • 1
  • 2
  • 7
2

EDIT

Using validate() appropriately and mockForConstraintsTest should work if the patch mentioned in the existing Grails bug is in place (Thanks to @codelark for bringing that up). In order to test the command object from a Web App standpoint (using controller) the below information would be helpful.

Test Command Object Using Controller action:-

A command object is only deemed as such when it is used as a parameter in one of the action method inside a controller. Refer Command Objects (Warning NOTE). Use SearchCommand in an action method, you should be able to assertEquals.

Sample:

void testSomething() {
        YourController controller = mockController(YourController) //Or instantiate
        SearchCommand commandUnderTest = new SearchCommand ()
        //Note the usage here. validate() does not take parameters
        commandUnderTest.basisBuild = ''
        commandUnderTest.validate()

        //Call your action
        controller.searchCommandAction(commandUnderTest)

        assert response.text == 'Returned'
        assertEquals "blank", commandUnderTest.errors['basisBuild']
    }

YourController's action:-

def searchCommandAction(SearchCommand sc){
    render "Returned"
}

Note:

With out the patch from the grails bug we see the below error in @Grails 2.1.4, 2.2.0 & 2.2.1

I get an error when I only correct the validation and use mockForConstraintTests without using controller action:

enter image description here

dmahapatro
  • 49,365
  • 7
  • 88
  • 117
0

You are using the validate method incorrectly. You never set the field on the class, so the field is null, not blank. Try changing your test as follows:

void testSomething() {
    SearchCommand commandUnderTest = new SearchCommand()
    commandUnderTest.basisBuild = ""

    assertFalse commandUnderTest.validate()
    assertEquals 'blank', commandUnderTest.errors['basisBuild']
}

Edit: There is also a grails bug when testing command classes that use the @Validatable annotation. There are some workarounds in the bug commentary.

codelark
  • 12,254
  • 1
  • 45
  • 49
  • I have already mentioned about the `validate()` method correction in my answer. Moreover, in Grails 2.x `mockForConstraintsTests` has to be either replaced by `mockDomainObject` (from `ControllerUnitTestMixins`) or instantiate (as shown in my answer). Following the fix proposed by you, would get an `assertion` failure in `assertFalse commandUnderTest.validate()`. – dmahapatro Apr 19 '13 at 19:43
  • This was extracted from a working example in grails 2.2.1. Why do you say `mockForConstraintsTest` must be replaced in 2.x? It is still in the non-deprecated testing API [See Javadoc](http://grails.org/doc/latest/api/grails/test/mixin/support/GrailsUnitTestMixin.html) – codelark Apr 19 '13 at 19:47
  • I am trying to prove myself wrong following you but it never worked for me in 2.1.4, 2.2.0 and 2.2.1. Created a brand new project, created the command object, created the test, ran the test. Enlighten me. :) – dmahapatro Apr 19 '13 at 20:13
  • http://pastebin.com/zZRKhC06 - contains the two files you need to create after a grails create-app. Then `grails test-app :unit` – codelark Apr 19 '13 at 20:26
  • @dmahapatro It appears the difference in our results is due to an unresolved grails bug. [See here.](http://jira.grails.org/browse/GRAILS-9162) Apparently there is an interaction problem between the annotation and the mock helper. Notice my code in the pastebin did *not* use the annotation. I'll update my answer with the additional detail. – codelark Apr 19 '13 at 20:40
  • The bug does not affect version 2.2 though.On the other hand, If you add `@Validateable`, you would see the same result as I do which I think is valid. The definition of command object is tightly coupled to a `controller`. Plus, `FooCommand` in your app is nothing but a POGO and is not a command object until attached to controller. Also refer (8.6 Applying Validation to Other Classes) from http://grails.org/doc/latest/guide/validation.html – dmahapatro Apr 19 '13 at 20:48
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28533/discussion-between-codelark-and-dmahapatro) – codelark Apr 19 '13 at 20:50