0

I have a problem with my Unit Test. This is my Unit Test:

void "Test the update action performs an update on a valid domain instance"() {
    given:
        def aclServiceMock = mockFor(AclService)
        aclServiceMock.demand.updateRolePermissions { Role role, Map, roleMap, List permissions -> return true }
        controller.aclService = aclServiceMock.createMock()

        def roleInstance = setupRoleController()

        mockCommandObject RoleCommand
        RoleCommand cmd = new RoleCommand(
            authority: roleInstance?.authority,
            description: roleInstance?.description
        )

    when:"A valid domain instance is passed to the update action"
        controller.update(roleInstance, cmd)

    then:"A redirect is issued to the show action"
        response.redirectedUrl == "/role/index"
        flash.message != null
        flash.error == null
}

And this is the result that I get from the terminal:

| Failure:  Test the update action performs an update on a valid domain instance(ph.gov.doe.core.acl.RoleControllerSpec)
|  Condition not satisfied:
flash.message != null
|     |       |
[:]   null    false
    at ph.gov.doe.core.acl.RoleControllerSpec.Test the update action performs an update on a valid domain instance(RoleControllerSpec.groovy:222)

I can't seem to figure out why my unit test on that particular method keeps failing. Maybe my Command Object mock is the key? Thanks in advance.

EDIT: condition should be 'response.redirectedUrl == "/role/index"', I just copied the wrong message cause i was fiddling with the code at the time.

EDIT: This is the controller method:

def update(Role roleInstance, RoleCommand roleCommand) {
    Map roleMap = [:]
    ArrayList collectPermission = [], getPermissions = [], roleList = []
    def savedRoleInstance

    /** collect selected permission into arraylist */
    collectPermission.addAll(params?.selectedPermission ?: [])
    getPermissions = Permission.findAllByIdInList(collectPermission)

    def roleEditInstance = Role.get(params?.roleId)

    /** Set data for validation of Role */
    roleCommand.with {
        id          = roleEditInstance?.id
        authority   = params?.authority
        description = params?.description
    }

    roleCommand.validate()        

    /** Check if the set of permission already exists */
    roleList = RolePermission.findAllByPermissionInListAndRoleNotEqual(getPermissions, Role.findByAuthority('ROLE_SUPERADMIN'))?.role

    def duplicateRolePermission = roleList.find { r -> r.getAuthorities().sort { it?.id } == getPermissions.sort { it?.id }  && r != roleEditInstance }

    if (collectPermission.isEmpty()) {
        flash.error = message(code: 'role.permissions.blank', args: [message(code: 'role.label', default: params?.authority)])
        respond roleInstance, model:[roleList: Role.list(), permissionList: Permission.findAllByAuthorityNotEqual('PERM_DASHBOARD_VIEW'), inheritPermission: params?.inheritPermission, selectedPermission: getPermissions], view: "edit"            
    } else if (roleCommand.hasErrors() || duplicateRolePermission != null) {
        bindData(roleCommand, roleInstance)

        if(duplicateRolePermission != null){
            flash.error = message(code: 'role.permissions.unique', args: [message(code: 'role.label', default: getPermissions?.description)])
        }

        respond roleCommand.errors, model:[roleInstance: roleCommand,roleList: Role.list(), permissionList: Permission.findAllByAuthorityNotEqual('PERM_DASHBOARD_VIEW'), inheritPermission: params?.inheritPermission, selectedPermission: getPermissions, roleId: roleEditInstance?.id], view: "edit"
    } else {
        /** Save the Role */
        roleMap = [authority: params?.authority, description: params?.description]
        def savedRole = aclService.updateRolePermissions(roleEditInstance, roleMap, getPermissions)

        if (currentAccount) {
           auditLogService.logEvent(currentAccount.emailAddress, "UPDATE_ROLE_SUCCESS", "Successfully updated role details.", true) 
        }

        flash.message = message(code: 'role.updated.message', args: [message(code: 'role.label', default: savedRole?.authority)])
        flash.id = savedRole?.id
        redirect action: 'view', params:[id: savedRole?.id]
    }
}
Francis
  • 1
  • 4
  • Can you show your controller code as well? – LeslieV Mar 15 '17 at 19:32
  • oh, yeah, sorry. i'll edit the post. – Francis Mar 15 '17 at 23:32
  • Wow, you have a lot going on in that controller method. :) I suspect that part of your issue is the params in this line do not match the actual signature of your method in your AclService: `aclServiceMock.demand.updateRolePermissions { Role role, Map, roleMap, List permissions -> return true }` and so it is not using your mock. Try removing the extra comma after Map: `aclServiceMock.demand.updateRolePermissions { Role role, Map roleMap, List permissions -> return true }` – LeslieV Mar 16 '17 at 01:16
  • @LeslieV oh, yeah. shoot. that's so clumsy. thanks for pointing that out. i tried running the test again, but still no luck. i'm getting the same error message. – Francis Mar 16 '17 at 05:46

1 Answers1

0

It seems that the app you're trying to test could be designed better. Lots of logic could be moved from controller to service (separation of concerns principle).

Also your test looks like integration-test rather then unit. So I would recommend you to get acquainted with interaction based testing.

Good luck!

Anton Hlinisty
  • 1,441
  • 1
  • 20
  • 35
  • 1
    Yeah, we're still in the process of improving everything, and we'll focus on making it more efficient once we've got the mehods working. And you're right, I think we'll be using integration testing instead. Thank you! – Francis Mar 17 '17 at 03:13
  • I would recommend to use unit, integration and functional tests at the same time. Here is a doc: http://docs.grails.org/latest/guide/testing.html – Anton Hlinisty Mar 17 '17 at 14:57
  • 1
    That's a good suggestion. I'll definitely bring that up to the team. Thank you! – Francis Mar 20 '17 at 01:15