Grails使用Spring Security Core Plugin测试用户角色自定义验证约束

时间:2011-04-30 21:17:10

标签: unit-testing grails spring-security gorm

我确信这是一个相当普遍的情况。我正在使用Spring Security Core插件,并且想要创建一个具有限于某些角色的Person的域模型:

class Workgroup {

Person manager
...

 static constraints = {
    manager(validator: {mgr ->
            // it feels like there should be a more elegant, groovy way of doing this.
            def auths = mgr.getAuthorities();
            def returny = false
            auths.each {
                if(it.authority == 'ROLE_MANAGER')
                {
                    returny = true
                }
            }
            return returny
        })
}

}

此测试失败了,就像一个mofo:

void testInvalidManager() {
    def nick = new Person(username:'Nick')
    def nonManagerRole = new Role(authority:'ROLE_EMPLOYEE')
    UserRole.create(nick,nonManagerRole)
    def awesome = new Workgroup(name:'mooCows', manager:nick)
    mockForConstraintsTests(Workgroup, [awesome])
    assertFalse awesome.validate()
    assertEquals "validator", awesome.errors["manager"]
}

testInvalidManager错误没有方法签名:users.UserRole.save()适用于参数类型:(java.util.LinkedHashMap)值:[[flush:false,insert:true]]可能的解决方案:wait(), any(),wait(long),use([Ljava.lang.Object;),isCase(java.lang.Object),each(groovy.lang.Closure)

groovy.lang.MissingMethodException:没有方法签名:users.UserRole.save()适用于参数类型:(java.util.LinkedHashMap)值:[[flush:false,insert:true]] 可能的解决方案:wait(),any(),wait(long),use([Ljava.lang.Object;),isCase(java.lang.Object),each(groovy.lang.Closure)     at users.UserRole.create(UserRole.groovy:32)     at users.UserRole.create(UserRole.groovy)     at users.UserRole $ create.call(Unknown Source)     at users.WorkgroupTests.testInvalidManager(WorkgroupTests.groovy:17)

整合比单元测试更好吗?我是否需要模拟UserRole(如果是,如何?)?这些类型的测试通常如何进行?

1 个答案:

答案 0 :(得分:2)

UserRole.create()来电save(),因此您需要使用mockDomain()而非mockForConstraintsTests()

但是,只有当你使用模拟测试域模型时才会这样,我永远不会这样做。在测试使用域类的控制器或其他类时,应该使用Grails中的模拟支持,但不应该使用真正的持久性,创建数据库(甚至是内存中)等等。通过删除该依赖关系,您将专注于当前层,相信其他层已经过适当测试。但是当你使用mocking来测试域类时,你真的只是在测试模拟框架。所以我总是对域类使用集成测试,因此它们针对真实数据库运行。

要回答代码示例中的隐含问题,我将约束写为

static constraints = {
   manager validator: { mgr ->
      mgr.authorities.find { it.authority == 'ROLE_MANAGER' } != null
   }
}

它的批量问题是,当一个常规for循环更可取时,你正在使用each(),因为你可以从for循环返回。仅当您真的想要在每个实例上调用闭包时才使用each()。这是一个比另一个更不时髦但使用for循环的那个:

static constraints = {
   manager validator: { mgr ->
      for (auth in mgr.getAuthorities()) {
         if (it.authority == 'ROLE_MANAGER') {
            return true
         }
      }
      return false
   }
}