【问题标题】:Grails testing user role custom validation constraints using Spring Security Core PluginGrails 使用 Spring Security Core Plugin 测试用户角色自定义验证约束
【发布时间】:2011-08-16 05:22:33
【问题描述】:

我确信这是一种相当普遍的情况。我正在使用 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) 在 users.UserRole.create(UserRole.groovy:32) 在 users.UserRole.create(UserRole.groovy) 在 users.UserRole$create.call(Unknown Source) 在 users.WorkgroupTests.testInvalidManager(WorkgroupTests.groovy:17)

集成比单元测试更能涵盖这方面的内容吗?我是否需要模拟 UserRole (如果需要,如何?)?这些类型的测试通常是如何进行的?

【问题讨论】:

    标签: unit-testing grails spring-security grails-orm


    【解决方案1】:

    UserRole.create() 调用save(),因此您需要使用mockDomain() 而不仅仅是mockForConstraintsTests()

    但前提是您可以使用模拟测试域模型,而我永远不会这样做。在测试控制器或其他使用域类的类时,应使用 Grails 中的模拟支持,但不应为真正的持久性、创建数据库(甚至在内存中)等问题所困扰。通过消除这种依赖关系,您将专注于当前层,相信另一层已经过适当的测试。但是当您使用模拟来测试域类时,您实际上只是在测试模拟框架。所以我总是对域类使用集成测试,以便它们针对真实数据库运行。

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

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

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

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

    【讨论】:

    • 这肯定是另一个问题或 grails-user 讨论的主题,但你为什么不用mockDomain() 测试域类呢?例如,我的域逻辑包括几个 findBy*()s,与 parent.children.find{} 相反 - 为什么会不好?我对您的意见非常感兴趣,因为我知道您在 Grails 中的角色。
    • 您应该使用 mockForConstraintsTests 测试域类,以验证您的域约束。否则,您可以使用 mockDomain 来提供类似于正确域对象的域对象,以便可以针对它们测试服务和控制器。
    猜你喜欢
    • 1970-01-01
    • 2013-02-04
    • 2015-12-12
    • 2011-07-21
    • 2012-02-17
    • 2013-12-09
    • 1970-01-01
    • 2018-01-29
    • 2011-08-31
    相关资源
    最近更新 更多