Sunday 3 June 2007

Grails 0.5.5 - testing controllers with Mocks and Expando

In this blog entry I would like to show you how to unit test a typical 'update' action in Grails using Groovy Mocks and the ExpandoMetaClass.

Let's assume we have an action like this:
 
 def updateword = {
     def word = Word.get( params.word_id )
     if(word) {
         word.pl = params.word_translation
         if(word.save()) {
             render("OK")
         }
         else {
             render("Error updating word")
         }
     }
     else {
         render("Word does not exist")
     }
 }
In brief, it updates a Word instance by getting a Word from the database, modifying its 'pl' property and saving it back to the database.

Now, how would you unit test the execution path where the "Error updating word" message gets rendered? To do that, you need a scenario where a Word instance gets returned from the database but fails to save back after the update operation. Here is how you can do it using Mocks and Expandos:
 void testUpdateExistingWordSaveFailure() {
     def mock = new MockFor(Word)
     def fakeWord = new Expando(save: {false})
 
     mock.demand.get { fakeWord }
     mock.use {
         def wc = new WordController()
         wc.params.word_translation = "tak"
         wc.updateword()
         assertEquals "Error updating word", 
                      wc.response.delegate.contentAsString
     }
 }

The flow of the test is as follows:
  1. Create a mock for the Word class
  2. Craete a fake word instance (Expando) which replaces the 'save' method
  3. Demand the Word class to return the faked word when the get method is called (exactly once)
  4. Use the mock and call the updateword closure
  5. Assert if the correct message was rendered to the browser
See the Unit & Integration Testing Controllers page to understand the last step - getting a text from the response.

7 comments:

hank said...

Hi Marcin,

I am testing the controller in my project now, but have a snag.

If the rendering in the action is "render(view:'edit')" rather than "render("text"), do you have any idea how to test this. It seems we can not use "contentAsString" property in this case. Great thanks!

Marcin Domanski said...

Hi,

When I was last looking at testing in Grails, I did know that, too. The online Grails docs didn't cover that and probably there was no answer to that question on the Grails user group, too.

Unfortunately I still don't know as I've stopped doing Grails for a while, though would be nice to know the answer ;-)

PS. Sorry for a very late response. I haven't realised until now that there is comment to this post...

Cheers,
Marcin

Anonymous said...

When some one searches for his required thing, so he/she wants to be available that in
detail, thus that thing is maintained over here.

Here is my site: honda s2000 for sale shop

Anonymous said...

Hello my loved one! I wish to say that this post is awesome, great
written and come with almost all significant infos. I would like to
peer more posts like this .

Check out my webpage: omron hr-100c heart rate monitor review

Anonymous said...

I visited many sites except the audio feature for audio songs present at this web site
is actually excellent.

Feel free to visit my page :: strapless monitor

Anonymous said...

Hey! Do you know if they make any plugins to safeguard against hackers?

I'm kinda paranoid about losing everything I've worked hard on.
Any tips?

Review my homepage - mazda 16x

Anonymous said...

WOW just what I was searching for. Came here by searching for colonialised

Feel free to surf to my web blog; toys shop online