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
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()
}
}
}
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.