开发者

Grails testing user role custom validation constraints using Spring Security Core Plugin

开发者 https://www.devze.com 2023-03-01 15:06 出处:网络
I\'m sure this is a fairly common situation. I\'m using the Spring Security Core plugin and want to create a domain model that has a Person limited to certain roles:

I'm sure this is a fairly common situation. I'm using the Spring Security Core plugin and want to create a domain model that has a Person limited to certain roles:

class Workgroup {

Person manager
...

 static con开发者_如何学Pythonstraints = {
    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
        })
}

}

This test fails like a 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 Error No signature of method: users.UserRole.save() is applicable for argument types: (java.util.LinkedHashMap) values: [[flush:false, insert:true]] Possible solutions: wait(), any(), wait(long), use([Ljava.lang.Object;), isCase(java.lang.Object), each(groovy.lang.Closure)

groovy.lang.MissingMethodException: No signature of method: users.UserRole.save() is applicable for argument types: (java.util.LinkedHashMap) values: [[flush:false, insert:true]] Possible solutions: 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)

Is this better covered in Integration than Unit Testing? Do I need to mock UserRole (if so, how?)? How are these types of tests normally done?


UserRole.create() calls save(), so you need to use mockDomain() instead of just mockForConstraintsTests().

But that's only if you're ok with testing the domain model with mocks, which I would never do. The mocking support in Grails should be used when testing Controllers or other classes that use domain classes but shouldn't be bothered with real persistence, creating a database (even in-memory), etc. By removing that dependency you're concentrating on the current tier, trusting that the other tier is already properly tested. But when you use mocking to test domain classes, you're really just testing the mocking framework. So I always use integration tests for domain classes so they run against a real database.

To answer the implicit question from your code example, I'd write the constraint as

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

The issue with its bulk is that you're using each() when a regular for loop would be preferable since you can return from a for loop. Use each() only when you really want to invoke the closure on every instance. Here's one that's less groovy than the other one but uses a for loop:

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

精彩评论

暂无评论...
验证码 换一张
取 消