Today I am going to explain some basic concept of Spock integration testing without redirected view. Here I am going to check returning model from action and how to test action when it is returning model?

class CreateAppController {
def addDetail() {
def playList = []
PlayDetail deatil = session.detail
 if (detail) {
    playList = PlayDetail.findAll { it?.detail?.id == detail?.id }
   [playList: playList, detail: detail]
 } 
 else {
   flash.message ="Please select a detail to continue or create one."
   redirect(action: 'index')
 }
}
}

Here I have defined the controller with name CreateAppController and action with name  addDetail . I am fetching playDetail from database with the help of detailId and if detail had session then action should return model with playList and detail.

Now I am going to write testcase for this action.

def 'test for addDetail when deatil had session'()
{
when:
WorkDetail detail = WorkDetail.findById('abc123')
RequestContextHolder.currentRequestAttributes().session.detail=detail
def model =createAppController.addDetail()
then:
assert createAppController.modelAndView.model.playList
assert createAppController.modelAndView.modelMap.playList
assert createAppController.modelAndView.model.detail
assert createAppController.modelAndView.modelMap.detail
assert createAppController.modelAndView.viewName=='/createApp/addDetail'
}

Here I have provided detail id as “abc123” because in database it has playDetail and by model and model-map. I am checking that model is null or it has some value. Now I am going to run the test-case and lets see what is the result ?.

java.lang.NullPointerException: Cannot get property 'model' on null object
at app.CreateAppControllerIntegrationSpec.test for addDetail when detail had session(CreateAppControllerIntegrationSpec.groovy:22)

Here it is giving null pointer exception and telling that model is null but playList had some data then why it is saying it is null.
Lets check the action once-again with some modification.

class CreateAppController {
def addDetail() {
def playList = []
PlayDetail deatil = session.detail
 if (detail) {
    playList = PlayDetail.findAll { it?.detail?.id == detail?.id }
    render(view: 'addDetail', model:[playList: playList, detail: detail]
 } 
  } else {
    flash.message = "Please select a detail to continue or create one.";
    redirect(action: 'index')
  }
 }
}

Here I have explicitly provided the view name.As we know in grails that if we are not providing the view name in action than the action renders the view with action name.Now lets check the test-case with same code and lets check what happens.

Here test-case got passed but lets think why? Now we came to conclusion that it is good practice to write rendering view name in action. So it will execute well while testing. Enjoy testing.