Reputation: 3216
I have test for the save action of a controller. It just executes the action with correct params, but the problem is on the redirectedUrl line: it is null.
Using the app, after saving the domain instance, I get the redirection to the show action and the show view is rendered correctly.
Any clues of what's the problem here?
The controller:
@Transactional(readOnly = true)
class FolderController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
...
@Transactional
def save(Folder folderInstance) {
if (folderInstance == null) {
notFound()
return
}
if (folderInstance.ehrId)
{
def ehr = ehr.Ehr.get(folderInstance.ehrId)
ehr.directory = folderInstance
ehr.save()
}
if (folderInstance.hasErrors()) {
respond folderInstance.errors, view:'create'
return
}
folderInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'folder.label', default: 'Folder'), folderInstance.id])
redirect folderInstance
}
'*' { respond folderInstance, [status: CREATED] }
}
}
...
}
The test:
@TestFor(FolderController)
@Mock(Folder)
class FolderControllerSpec extends Specification {
...
void "Test the save action correctly persists an instance"() {
when:"The save action is executed with a valid instance"
response.reset()
populateValidParams(params)
def folder = new Folder(params)
controller.save(folder)
println folder.errors // no errors
then:"A redirect is issued to the show action"
response.redirectedUrl == '/folder/show/1'
controller.flash.message != null
Folder.count() == 1
}
...
}
The output:
junit.framework.AssertionFailedError: Condition not satisfied:
response.redirectedUrl == '/folder/show/1'
| | |
| null false
org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletResponse@112b2f1
at directory.FolderControllerSpec.Test the save action correctly persists an instance(FolderControllerSpec.groovy:61)
Upvotes: 0
Views: 573
Reputation: 3216
I forgot to add the allowedMethods field.
The first problem was that the generated tests doesn't sets the right request method for the correspondent actions, so to call .save() this is needed: controller.request.method = "POST"
Then what @user1690588 suggested (request.format = 'form') did the trick to get the right redirectedUrl.
My final test looks like this:
void "Test the save action correctly persists an instance"() {
when:"The save action is executed with a valid instance"
response.reset()
populateValidParams(params)
def folder = new Folder(params)
controller.request.method = "POST"
request.format = 'form'
controller.save(folder)
then:"A redirect is issued to the show action"
response.redirectedUrl == '/folder/show/1'
controller.flash.message != null
Folder.count() == 1
}
Upvotes: 1
Reputation: 7619
Grails scaffold controllers are smarter controllers. They respect the request format and generate the response accordingly.
For example your save action -- it redirects to the show action if the request format is form
otherwise it returns saved domain instance with status CREATED
.
Following code is responsible for this
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'folder.label', default: 'Folder'), folderInstance.id])
redirect folderInstance
}
'*' { respond folderInstance, [status: CREATED] }
}
And in you test cases, your request is not of form
type and hence redirectedUrl
is null.
To make form
request, add following code in you test case before making save call--
request.format = 'form'
Hope this helps.
Upvotes: 1