Groupie feedhttp://nerderg.com/
Groupie feed feedUnit testing with SpringSecurityUtilshttp://nerderg.com/home
<div class="article">
<h1>Unit testing with SpringSecurityUtils</h1>Unit testing controllers is often overlooked in favour of Integration testing simply because of all the services you need to mock out while testing, that is, it's simply easier to do Integration tests when the mocked Domain classes etc. are not as full featured as the real ones. The trouble is unit tests are generally much faster, they don't rely on resources like DB and specify the tests a lot better, you are only testing this bit, not the services.<br /><br />So it is desirable in many cases to be able to unit test a controller where possible. Spring Security is one place that people get hung up when unit testing. For example if you have controller action that looks something like this:-<br /><br /><div class="code"> def dashboard = {<br /> if (SpringSecurityUtils.ifAllGranted(&quot;ROLE_ADMIN&quot;)) {<br /> return redirect(controller: &quot;admin&quot;, action: &quot;index&quot;)<br /> }<br />...<br /></div><br />You need to mock out SpringSecurityUtils.ifAllGranted which is a static method, otherwise it will try and get a SecurityContext etc. etc. which you just don't need for this test.<br /><br />So to mock this out just use the metaClass and replace the static method like so:-<br /><br /><div class="code"> SpringSecurityUtils.metaClass.'static'.ifAllGranted = { String role -&gt;<br /> return false<br /> }<br /></div><br />Now you control that method however this &quot;fix&quot; comes with a WARNING: when you replace a method this way it stays replaced while the JVM is alive, so if you have functional tests that rely on this method and just use grails test-app to do all tests chances are your functional tests will fail.<br /><br />To remove your meta programming methods you would have to do something like this in tearDown() :-<br /><br /><div class="code">protected void tearDown() {<br /> super.tearDown()<br /> SpringSecurityUtils.metaClass = null;<br />}<br /></div><br />However there is a much neater way of doing it shown here -&gt; <a href="http://www.jworks.nl/blog/show/75/remove-groovy-metaclass-methods">http://www.jworks.nl/blog/show/75/remove-groovy-metaclass-methods</a>. (thanks <span class="tweet-user-name"><span class="tweet-full-name">Marcin Erdmann</span></span> and Erik Pragt!)<br /><br />What you do is call registerMetaClass(Thing.class) in your unit tests setUp() and define the metaclass changes then the metaClass will be cleaned up for you on tearDown(). It'd look like this:-<br /><br /><div class="code">protected void setUp() {<br /> super.setUp()<br /> registerMetaClass(SpringSecurityUtils)<br />}<br /></div><br />enjoy.<br />--<br />
</div>http://nerderg.com/homeAdding bindData() to a Servicehttp://nerderg.com/home
<h1>Adding bindData() to a Service</h1><div class="article">Sometimes when you don't want to repeat yourself in controllers you
need to add some support code to a grails Service. If you do this then
you quickly reach the point where you'd really like bindData() to be
available on a Service. <a href="http://jts-blog.com/?p=215">JT's blog</a> has a nice little teaser there, but it's not quite the same as having bindData() just being available, so how do you do it?<br />
<br />
A. use GroovyDynamicMethodsInterceptor<br />
<br />
Here is a trivial example:<br />
<div class="code">package com.nerderg.serviceExample<br />import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod<br />import org.codehaus.groovy.grails.commons.metaclass.GroovyDynamicMethodsInterceptor<br /><br />class CommandSupportService {<br /> static transactional = true<br /><br /> CommandSupportService() {<br /> GroovyDynamicMethodsInterceptor i = new GroovyDynamicMethodsInterceptor(this)<br /> i.addDynamicMethodInvocation(new BindDynamicMethod())<br /> }<br /><br /> def populateCommand(params) {<br /> def myCommand = new myCommand()<br /> bindData(myCommand, params)<br /> return myCommand<br /> }<br /></div>So what we're looking at here is adding the DynamicMethod <a href="http://www.grails.org/doc/1.1.1/api/org/codehaus/groovy/grails/web/metaclass/BindDynamicMethod.html">BindDynamicMethod</a> to a DynamicMethodInterceptor added to our service class when it's constructed.<br /></div><br />http://nerderg.com/homeMore testing Grails Spring Securityhttp://nerderg.com/home
<h1>More testing Grails Spring Security</h1><div style="" id="" class="article">One thing I missed in my last article on integration testing with Grails Spring Security plugin was a test to see that you weren't authenticated, or couldn't access the controller method. So I put that test in and was surprised that I could get to the controller! So the Secure controller looked like this:<br /><br /><div class="code">package com.nerderg.tester<br /><br />import grails.plugins.springsecurity.Secured<br />class SecureController {<br /><br /> @Secured(['ROLE_ADMIN'])<br /> def index = {<br /> render &quot;Secure access only&quot;<br /> }<br />}</div><br />Of course this is because the test code calls index() directly, missing the security filter. That means you can unit test your annotated controllers function sans security if you want, but it makes it hard to test the security unless you use a web test (WebDriver/Geb).<br /><br />So what use is the technique I described previously? We'll if you use the SpringSecurityUtil functions you still need to be authenticated. For example if your controller looked like this:<br /><br /><div class="code">package com.nerderg.tester<br /><br />import grails.plugins.springsecurity.Secured<br />import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils<br /><br />class SecureController {<br /><br /> def index = {<br /> if(SpringSecurityUtils.ifAllGranted(&quot;ROLE_ADMIN&quot;)){<br /> render &quot;Secure access only&quot;<br /> } else {<br /> render &quot;Please log in&quot;<br /> }<br /> }<br />}</div><br />In this case the test will fail if you're not logged in, and just to be sure that it fails here is the updated test code:<br /><br /><div class="code">...<br /> void testIndexNotLoggedIn() {<br /> controller.index()<br /> println controller.response.contentAsString<br /> assert &quot;Please log in&quot; == controller.response.contentAsString<br /> }<br />... <br /> void testIndexLoggedIn() {<br /> def authToken = new UPAT(&quot;me&quot;, &quot;password&quot;)<br /><br /> try {<br /> authenticationManager.authenticate(authToken)<br /> } catch(e) {<br /> fail(&quot;exception <span>$</span>e should not be thrown&quot;)<br /> }<br /><br /> controller.index()<br /> println controller.response.contentAsString<br /> assert &quot;Secure access only&quot; == controller.response.contentAsString<br /> }<br /></div><br />BUT this test will <span style="font-weight: bold;">fail</span> because I needed to do one more thing to authenticate the user. I need to set the Authentication in the SecurityContext. So here is the full working test code:<br /><br /><div class="code">package com.nerderg.tester<br /><br />import grails.test.*<br />import org.springframework.security.authentication.UsernamePasswordAuthenticationToken as UPAT<br />import org.springframework.security.authentication.AuthenticationManager<br />import org.springframework.security.authentication.BadCredentialsException<br />import org.springframework.security.core.context.SecurityContextHolder;<br /><br />class SecureControllerIntegrationTests extends ControllerUnitTestCase {<br /><br /> def authenticationManager<br /><br /> protected void setUp() {<br /> super.setUp()<br /> }<br /><br /> protected void tearDown() {<br /> super.tearDown()<br /> }<br /><br /> void testIndexNotLoggedIn() {<br /> controller.index()<br /> println controller.response.contentAsString<br /> assert &quot;Please log in&quot; == controller.response.contentAsString<br /> }<br /><br /> void testIndexLoggedIn() {<br /> def authToken = new UPAT(&quot;me&quot;, &quot;password&quot;)<br /><br /> try {<br /> def auth = authenticationManager.authenticate(authToken)<br /> SecurityContextHolder.getContext().setAuthentication(auth)<br /> } catch(e) {<br /> fail(&quot;exception <span>$</span>e should not be thrown&quot;)<br /> }<br /><br /> controller.index()<br /> println controller.response.contentAsString<br /> assert &quot;Secure access only&quot; == controller.response.contentAsString<br /> }<br />}<br /></div><br />Note the SecurityContextHolder.getContext().setAuthentication(auth) in that code. It pays to not skimp on your tests! It also pays to look at the source <a href="http://github.com/grails-plugins/grails-spring-security-core/blob/master/src/java/org/codehaus/groovy/grails/plugins/springsecurity/SpringSecurityUtils.java">SpringSecurityUtils.java</a>.<br /></div><br /><br />http://nerderg.com/homeIntegration Tests on a secured controller in Grailshttp://nerderg.com/home
<h1>Integration tests on a secured controller in Grails</h1><div class="article"><p style="" class="para" id="">I was helping out a client the other day who is using the Grails Sring Security Core plugin to secure their Grails app controllers. I must say I've been slack and only ever used the old Acegi plugin. Anyway their main interest was to test the secured controllers using integration tests and asked me to help... #1 issue how to authenticate a user in a test? Sounds simple enough, but unless you have used Spring Security itself and understand the conventions well enough, the documentation for the plugin is sadly lacking. Come to think of it the testing doco in Grails and for the plugins is really not up to standard - the examples are all far to trivial!</p><p style="" class="para" id="">I thought I knew how to do this, but on site, in front of the (very nice) client, I couldn't pull the rabbit out of the hat and answer the one question they really wanted answered. I vowed to document the answer, and here it is:-</p><p style="" class="para" id="">The answer is, as you would expect, create an authentiactionToken and authenticate it, but what do you call? Here's the example test case. It's based on the example tutorial here <a href="http://burtbeckwith.github.com/grails-spring-security-core/docs/manual/index.html">http://burtbeckwith.github.com/grails-spring-security-core/docs/manual/index.html</a><br /></p><span style="font-family: monospace;"><div class="code">package com.nerderg.tester<br /><br />import grails.test.*<br />import org.springframework.security.authentication.UsernamePasswordAuthenticationToken as UPAT<br />import org.springframework.security.authentication.AuthenticationManager<br />import org.springframework.security.authentication.BadCredentialsException<br /><br />class SecureControllerIntegrationTests extends ControllerUnitTestCase {<br /><br /> def authenticationManager<br /><br /> protected void setUp() {<br /> super.setUp()<br /> }<br /><br /> protected void tearDown() {<br /> super.tearDown()<br /> }<br /><br /> void testIndex() {<br /> def authToken = new UPAT(&quot;me&quot;, &quot;passwrd&quot;)<br /> try {<br /> authenticationManager.authenticate(authToken)<br /> } catch(e) {<br /> assert e instanceof BadCredentialsException<br /> }<br /> authToken = new UPAT(&quot;me&quot;, &quot;password&quot;)<br /> try {<br /> authenticationManager.authenticate(authToken)<br /> } catch(e) {<br /> fail(&quot;exception <span><span><span><span><span>$</span></span></span></span></span>e should not be thrown&quot;)<br /> }<br /> controller.index()<br /> println controller.response.contentAsString<br /> assert &quot;Secure access only&quot; == controller.response.contentAsString<br /> }<br />}</div><br /></span><p style="" class="para" id="">So the trick is to create a <a href="http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/authentication/UsernamePasswordAuthenticationToken.html">UsernamePasswordAuthenticationToken</a> and use the injected authenticationManager to authenticate it. Simple when you know that Spring Security uses an <a href="http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/authentication/AuthenticationManager.html">AuthenticationManager</a> and that the convention is that would be injected in.</p></div>http://nerderg.com/home