【问题标题】:Grails Unit Testing a method with command objectGrails 使用命令对象对方法进行单元测试
【发布时间】:2017-03-15 02:05:38
【问题描述】:

我的单元测试有问题。这是我的单元测试:

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
}

这是我从终端得到的结果:

| 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)

我似乎无法弄清楚为什么我对该特定方法的单元测试总是失败。也许我的命令对象模拟是关键?提前致谢。

编辑:条件应该是 'response.redirectedUrl == "/role/index"',我只是复制了错误的消息,因为我当时正在摆弄代码。

编辑:这是控制器方法:

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]
    }
}

【问题讨论】:

  • 你也可以显示你的控制器代码吗?
  • 哦,是的,对不起。我会编辑帖子。
  • 哇,你在那个控制器方法中有很多事情要做。 :) 我怀疑您的部分问题是这一行中的参数与您的 AclService 中的方法的实际签名不匹配:aclServiceMock.demand.updateRolePermissions { Role role, Map, roleMap, List permissions -> return true } 因此它没有使用您的模拟。尝试删除 Map 后多余的逗号:aclServiceMock.demand.updateRolePermissions { Role role, Map roleMap, List permissions -> return true }
  • @LeslieV 哦,是的。射击。太笨拙了。感谢您指出了这一点。我尝试再次运行测试,但仍然没有运气。我收到了同样的错误信息。

标签: unit-testing grails spock command-objects


【解决方案1】:

您尝试测试的应用似乎可以设计得更好。许多逻辑可以从控制器转移到服务(separation of concerns 原则)。

您的测试也看起来像集成测试而不是单元。所以我建议你熟悉interaction based testing。

祝你好运!

【讨论】:

  • 是的,我们仍在改进一切,一旦方法奏效,我们将专注于提高效率。你是对的,我认为我们将使用集成测试。谢谢!
  • 我建议同时使用单元、集成和功能测试。这是一个文档:docs.grails.org/latest/guide/testing.html
  • 这是个好建议。我一定会把它带到团队中。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2017-05-17
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多