Archive

Posts Tagged ‘Unit Testing’

Grails 2 Unit Tests – Undocumented Properties

May 15th, 2012 No comments

GrailsUnitTestMixin (and its descendents DomainClassUnitTestMixin, ServiceUnitTestMixin, etc) give your test classes some static and instance variables that aren’t mentioned in the docs yet. You get applicationContext, grailsApplication, config, and messageSource. Previously, if you had code that needed a grailsApplication (such as the JSON configurations), you had to set it up yourself. Now you get it for free. The mixin also implements the shouldFail method from GroovyTestCase so you can keep that functionality even though your tests are now JUnit 4 based.

Categories: grails, Testing, unit test Tags: ,

When dynamic programming backfires

November 20th, 2009 2 comments

I love Groovy’s meta-programming capabilities.  Duck typing, DSLs, ExpandoMetaClass… it’s all great until you blow your arm off with them and spend two hours picking the pieces back up.  Such was my experience today as I was trying to set up my first unit test for a Grails controller.  I needed to pass in some parameters.  As I just wrote in my last post, the grails user guide has information on integration testing controllers, but nothing more than a brief mention of the ControllerUnitTestCase.  Unfortunately, searching for phrases like “grails unit test controller” on Google turn up posts from last Fall, before the ControllerUnitTestCase was released with Grails 1.1.  Don’t ask me why I didn’t just search for ControllerUnitTestCase from the start.  20/20 hindsight.

Working with what I could find, I came across a blog post from March 2008 that covered integration testing with controllers, much like the grails User Guide.  It at least had some explicit examples of how to pass in parameters, so I hoped the approach would work with my ControllerUnitTestCase implementation.  Using the code snippets in the post as a guide, I setup my test something like this:

controller.request.params = [layoutType:'filmstrip',compKey:'testKey']
controller.create()

This looks good, right?  The test scaffolding connects the injected params property of the controller with the params property of the request.  Should work like a charm.

And so started my descent into WTF Land.

The tests compiled and ran fine, except that no params were getting passed through to the controller.  I assumed that the old documentation for integration testing no longer exactly applied for the new unit test setups.  Eventually I dug through enough of ControllerUnitTestCase, MvcUnitTestCase, and MockUtils that I figured out there was a way to get direct access to the params property of the controller.  “Makes sense,” I thought, “sort of a mini-mock.  Who needs the request for a unit test?”  Great, so let’s try this:

controller.params = [layoutType:'filmstrip',compKey:'testKey']
controller.create()

Run again and…

groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: params for class: YourController

Erk.  Closer inspection of grails.test.MockUtils.addCommonWebProperties() reveals how the params property is added to the controller class with only a get method.  Okay, so we can still manipulate the map once we get it.  One more try:

controller.params.putAll([layoutType:"filmstrip",compKey:'testKey'])
controller.create()

Success!  Finally, information is going where it needs to be.  I later realized that section 9.2 of the user guide does actually show an example similar to this, except that it sets each item on params individually:

def controller = new AuthenticationController()
controller.params.login = "marcpalmer"
controller.params.password = "secret"
controller.params.passwordConfirm = "secret"
controller.signup()

“Oh well,” I say to myself, “at least I got it working.  I’d better post a comment on that old blog post so that others know the new way to set parameters.”  I returned to the blog page, moved down to the comments section… and saw that someone else had posted a comment just last month thanking the author for the good information.  Wait a second… you normally don’t thank someone if their examples don’t work.  So I scrolled up and took a closer look at the examples again:

controller.request.parameters = [sender:'me',msg:'test']
controller.create()

Anyone with a better eye for detail than me see the difference that sent me down the rat hole? It’s request.parameters, not request.params as I had entered.  For the 100th time today, Doh!

But wait a second (or an hour, as the case may be)… If I was calling request.params and there is no params property, how did my test run at all?  Dig, dig, dig… It turns out that the request is a GrailsMockHttpServletRequest object.  Scanning through that class, I see the ever so powerful and ever so dangerous setProperty(String name, value) override.  If you try to set a property that doesn’t exist, it adds the value as an entry in the request’s attributes map.  So the test scaffolding was perfectly happy with my request.params call.  It nicely tucked my params map away in the attributes and continued on its way.

Sigh…it almost makes me miss compile-time method checking… but not quite.

ControllerUnitTestCase: Documentation Has Arrived

November 19th, 2009 No comments

My team started on our first Grails app back in mid-August.  I set out to provide good examples of using the new testing features in Grails 1.1 to encourage the rest of the team.  Domain class testing went great, as did Service testing.  Unfortunately, there wasn’t any documentation on the ControllerUnitTestCase class in the Grails User Guide, and I couldn’t find any blog or forum posts to help out.  I tried creating an instance of it and tossing in a call to mockController(), but I didn’t get very far.  I had to shift focus to other tasks before I could dive into the source code itself and figure out what it did, so progress stopped for a while.

Fast forward to today when I finally had a strong need for a controller unit test setup.  I dove into the code and realized three things very quickly:

  1. You don’t need to call mockController().  It does that for you based on the name of the test class itself.
  2. You don’t want to call the constructor of your controller class in the test cases.  Use the newInstance() method instead so that all the proper scaffolding is put in place.
  3. You don’t even have to call newInstance() most of the time because the setUp() method inits a controller variable for you already.

Doh!  I wish I had taken 15 minutes back in August to look at the source.  It would have saved quite a bit of time by encouraging us to get proper controller test cases in place faster.

To add insult to injury, after spending that time and more getting some test cases just right, I decided to try a search for more documentation online again.   This time there was an answer to my query for help.  A post to the grails-user mailing list less than a month ago generated several responses with useful info, including Scott Davis posting about the most recent addition to his Mastering Grails series which was published just days before the post.

So nine months after the release of Grails 1.1 there is now good documentation on this great piece.  Many thanks to those who pulled it together.

Corrections to Grails Documentation

September 5th, 2009 No comments

Here are two quick tips for anyone working with Grails 1.1.1:

1) The User Guide has conflicting info about cascading persistence.   Section 5.2.1.2 says “The default cascading behaviour is to cascade saves and updates, but not deletes unless a belongsTo is also specified.” Section 5.3.3 says, “If you do not define belongsTo then no cascades will happen and you will have to manually save each object.”

The former, 5.2.1.2, is correct. Create and Update actions are cascaded for one-to-many relations. However, hey are not cascaded for one-to-one relations.

2) Section 9.1 (Unit Testing) demonstrates how to pass in a list to the mockDomain(clazz, instanceList) call.  It then says that you can check that list to verify that persistence actions behaved as expected.  This is no longer correct.  The list is copied inside the mockDomain call.  To get access to the list of persisted objects for a class, use the MockUtils.TEST_INSTANCES map with the class name as the key.  For example:

def testInstances = []
mockDomain(Item, testInstances)
def i = new Item(name:"foo").save()
assertEquals 0, testInstances.size()
testInstances = MockUtils.TEST_INSTANCES[Item]
assertEquals 1, testInstances.size()

And in case you try the same thing as me, the mocking behavior does not support cascades.