Grails 使用 Spring Security Core Plugin 测试用户角色自定义验证约束
Posted
技术标签:
【中文标题】Grails 使用 Spring Security Core Plugin 测试用户角色自定义验证约束【英文标题】:Grails testing user role custom validation constraints using 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 (如果需要,如何?)?这些类型的测试通常是如何进行的?
【问题讨论】:
【参考方案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 来提供类似于正确域对象的域对象,以便可以针对它们测试服务和控制器。以上是关于Grails 使用 Spring Security Core Plugin 测试用户角色自定义验证约束的主要内容,如果未能解决你的问题,请参考以下文章
Grails - grails-spring-security-rest - 无法从 application.yml 加载 jwt 机密
使用 Spring Security Grails 插件编码密码
Grails + spring-security-core:用户登录后如何分配角色?