Eric V
Eric V

Reputation: 249

Grails 2 unit tests are generated and don't run as expected and produce a run time error

I have a Domain classs

class File {
    String name
    String path

    static constraints = {
        name nullable:false
        path nullable:false
    }
}

The generated controller

class FileController {

static allowedMethods = [create: ['GET', 'POST'], edit: ['GET', 'POST'], delete: 'POST']

def index() {
    redirect action: 'list', params: params
}

def list() {
    params.max = Math.min(params.max ? params.int('max') : 10, 100)
    [fileInstanceList: File.list(params), fileInstanceTotal: File.count()]
}

def create() {
    switch (request.method) {
    case 'GET':
        [fileInstance: new File(params)]
        break
    case 'POST':
        def fileInstance = new File(params)
        if (!fileInstance.save(flush: true)) {
            render view: 'create', model: [fileInstance: fileInstance]
            return
        }

        flash.message = message(code: 'default.created.message', args: [message(code: 'file.label', default: 'File'), fileInstance.id])
        redirect action: 'show', id: fileInstance.id
        break
    }
}

def show() {
    def fileInstance = File.get(params.id)
    if (!fileInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'file.label', default: 'File'), params.id])
        redirect action: 'list'
        return
    }

    [fileInstance: fileInstance]
}

def edit() {
    switch (request.method) {
    case 'GET':
        def fileInstance = File.get(params.id)
        if (!fileInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'file.label', default: 'File'), params.id])
            redirect action: 'list'
            return
        }

        [fileInstance: fileInstance]
        break
    case 'POST':
        def fileInstance = File.get(params.id)
        if (!fileInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'file.label', default: 'File'), params.id])
            redirect action: 'list'
            return
        }

        if (params.version) {
            def version = params.version.toLong()
            if (fileInstance.version > version) {
                fileInstance.errors.rejectValue('version', 'default.optimistic.locking.failure',
                          [message(code: 'file.label', default: 'File')] as Object[],
                          "Another user has updated this File while you were editing")
                render view: 'edit', model: [fileInstance: fileInstance]
                return
            }
        }

        fileInstance.properties = params

        if (!fileInstance.save(flush: true)) {
            render view: 'edit', model: [fileInstance: fileInstance]
            return
        }

        flash.message = message(code: 'default.updated.message', args: [message(code: 'file.label', default: 'File'), fileInstance.id])
        redirect action: 'show', id: fileInstance.id
        break
    }
}

def delete() {
    def fileInstance = File.get(params.id)
    if (!fileInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'file.label', default: 'File'), params.id])
        redirect action: 'list'
        return
    }

    try {
        fileInstance.delete(flush: true)
        flash.message = message(code: 'default.deleted.message', args: [message(code: 'file.label', default: 'File'), params.id])
        redirect action: 'list'
    }
    catch (DataIntegrityViolationException e) {
        flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'file.label', default: 'File'), params.id])
        redirect action: 'show', id: params.id
    }
}

and the generated testcase

@TestFor(FileController)
@Mock(File)
class FileControllerTests {


def populateValidParams(params) {
  assert params != null
  params["name"] = 'someValidName'
  params["path"] = 'someValidPath'
}

void testIndex() {
    controller.index()
    assert "/file/list" == response.redirectedUrl
}

void testList() {

    def model = controller.list()

    assert model.fileInstanceList.size() == 0
    assert model.fileInstanceTotal == 0
}

void testCreate() {
   def model = controller.create()

   assert model.fileInstance != null
}

void testSave() {
    controller.save()

    assert model.fileInstance != null
    assert view == '/file/create'

    response.reset()

    populateValidParams(params)
    controller.save()

    assert response.redirectedUrl == '/file/show/1'
    assert controller.flash.message != null
    assert File.count() == 1
}

void testShow() {
    controller.show()

    assert flash.message != null
    assert response.redirectedUrl == '/file/list'


    populateValidParams(params)
    def file = new File(params)

    assert file.save() != null

    params.id = file.id

    def model = controller.show()

    assert model.fileInstance == file
}

void testEdit() {
    controller.edit()

    assert flash.message != null
    assert response.redirectedUrl == '/file/list'


    populateValidParams(params)
    def file = new File(params)

    assert file.save() != null

    params.id = file.id

    def model = controller.edit()

    assert model.fileInstance == file
}

void testUpdate() {
    controller.update()

    assert flash.message != null
    assert response.redirectedUrl == '/file/list'

    response.reset()


    populateValidParams(params)
    def file = new File(params)

    assert file.save() != null

    // test invalid parameters in update
    params.id = file.id
    params["name"] = null
    params["path"] = null

    controller.update()

    assert view == "/file/edit"
    assert model.fileInstance != null

    file.clearErrors()

    populateValidParams(params)
    controller.update()

    assert response.redirectedUrl == "/file/show/$file.id"
    assert flash.message != null

    //test outdated version number
    response.reset()
    file.clearErrors()

    populateValidParams(params)
    params.id = file.id
    params.version = -1
    controller.update()

    assert view == "/file/edit"
    assert model.fileInstance != null
    assert model.fileInstance.errors.getFieldError('version')
    assert flash.message != null
}

void testDelete() {
    controller.delete()
    assert flash.message != null
    assert response.redirectedUrl == '/file/list'

    response.reset()

    populateValidParams(params)
    def file = new File(params)

    assert file.save() != null
    assert File.count() == 1

    params.id = file.id

    controller.delete()

    assert File.count() == 0
    assert File.get(file.id) == null
    assert response.redirectedUrl == '/file/list'
}
}

I have added the correct parameters for passing and failing test cases but there are still run time errors and the code that is generated in the controller doesn't line up with the code that is generated in the testcases. The testcases call methods in the controller that don't exist.

here is the error code / stack trace

groovy.lang.MissingMethodException: No signature of method: FileController.update() is applicable for argument types: () values: []
Possible solutions: create(), putAt(java.lang.String, java.lang.Object), delete(), edit(), isCase(java.lang.Object), split(groovy.lang.Closure)
    at FileControllerTests.testUpdate(FileControllerTests.groovy:98)

So there is basically no controller method called update since the controllers for edit and up date have been combined and use the request.method = 'POST' or 'GET' to fallow the appropriate action.

So basically my question is how do I get the correct unit test cases to be generated? Or am I missing something else completely?

I am using grails 2.1.1

Upvotes: 0

Views: 417

Answers (2)

Eric V
Eric V

Reputation: 249

So this discrepancy happened when I updated the templating files with the twitter bootstrap scaffolding files. They didn't have an updated Test.groovy file in the scaffolding sources.

I had to update the Test.groovy file to correspond to the new Controller.groovy file.

Upvotes: 0

ikumen
ikumen

Reputation: 11643

The code you have there looks like boiler plate scaffolding templates, so I'm assuming at some point you ran generate-all against File domain class. In doing so it probably created your FileController and corresponding FileControllerTest with all the "crud" actions/tests.

Just taking a guess here, but at some point you may have deleted your update action in FileController but left the FileControllerTest in place, which leaves you with

//in FileControllerTests
void testUpdate() {
    controller.update()
    ...
}

Just update your test class - remove the testUpdate or comment it out if you think you'll need it later.

Upvotes: 1

Related Questions