Unit testing Grails controllers with duplicate form submission check functionality

I’ve been doing some Grail 2.0.1 development recently. I like the maturity of framework and the ease of doing things.

One of the things Grails comes with is a simple way of avoiding duplicate form submission. Have a look at the code bellow:

def myControllerMethod(){
  withForm{
    render “theGoodStuff”
  } .invalidToken {
    render “theBadStuff”
  }
}

That’s the controller bit. In your view you need to enable use of that feature by passing useToken parameter to form tag:

<g:form action=”myControllerMethod” useToken=”true”></g:form>

It looks very simple and elegant. However when we would like to test the controller we need to make sure we match the token when calling the method.

Documentation on testing Grails application and this particular functionality contains the way of doing so, however I found it not working with Grails 2.0.1.  Not much was blogged about it so I looked through the mailing lists. I found one trail and a bug report for this issue.

Anyway, to make it work, the piece of documentation from Grails, version 1.4.x explains how to do it, and it works.

In controller test method we need to place this code:

…
def token = SynchronizerTokensHolder.store(session)
params[SynchronizerTokensHolder.TOKEN_URI] = '/myController/myControllerMethod’
params[SynchronizerTokensHolder.TOKEN_KEY] = token.generateToken(params[SynchronizerTokensHolder.TOKEN_URI])

controller.myControllerMethod()
…

Happy testing. Greg

Useful links:

http://grails.1312388.n4.nabble.com/grails-2-0-testing-controller-with-withForm-invalid-notation-td4316150.html
http://jira.grails.org/browse/GRAILS-8504
http://grails.org/doc/1.4.x/guide/9.%20Testing.html
http://grails.org

4 thoughts on “Unit testing Grails controllers with duplicate form submission check functionality

  1. You say this is for unit testing, but it seems more fit for integration testing, seeing as you’re using the session and mucking with the SynchronizerTokensHolder…

    Unit tests should not have any outside dependencies… such as a session.

    A better solution would be to mock the mechanism in which grails uses to determine whether or not the token is valid.

    This method works in 2.0.4, but I don’t see why it wouldn’t work in 2.0.1…

    Here’s how to do it:

    import org.codehaus.groovy.grails.web.metaclass.InvalidResponseHandler
    import org.codehaus.groovy.grails.web.metaclass.ValidResponseHandler

    class MyControllerTests {

    def myActionTestValidToken() {

    // override the default withForm
    controller.metaClass.withForm = { Closure c ->

    // mock a valid token
    return new ValidResponseHandler(c?.call())

    }

    }

    def myActionTestInvalidToken() {

    // override the default withForm
    controller.metaClass.withForm = { Closure c ->

    // mock an invalid token
    return new InvalidResponseHandler()

    }

    }

    }

    1. Hi Todd. Thanks for your comment.
      You are right. It is a better way of testing token form submission. I do agree that the method shown by me looks a bit like integration test as collaborators are not mocked but real.

      However, at the time I was writing the post there was no better resources about the ways of testing with Toke and form submission.
      Thanks for sharing.

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 )

Facebook photo

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

Connecting to %s