Saturday, April 04, 2009

Testing Controllers That Are Protected By JSecurity Plugin

It can be a challenge to write a test case to test an action that depends on the current user. For example, the list action only returns the records that is accessible by the current user.

If you use the JSecurity Plugin, chances are you will use SecurityUtils.getSubject() to refer to the current user. If the user logs in through the login form provided by the plugin, the user name is stored as SecurityUtils.getSubject().principal. What we want to do is to find a way to inject the "current" user name during the test.

This is how I did it. In FooController, I define getSubject and list like this:

class FooController {

def getSubject = {
return SecurityUtils.getSubject()
}

def list = {
def subject = getSubject()

// Restrict results in listing
...
[fooInstanceList: results, fooInstanceListTotal: total]
}
}

and the test:

void testList() {
FooController.metaClass.getSubject = { return [principal: 'user1'] }
def ctrl = new FooController()
ctrl.list()
...
}

In line 1, just before the FooController instance is created, the getSubject closure is modified to return a map that contains principal as the key. When the list action is invoked, the getSubject() method will return the map. That way, the listing will be restricted to the records which are accessible by the user user1.

No comments: