2

我在我的grails项目中使用了Spring安全性。我已经安装了spring-security-core插件和spring-security-ui插件。如何在使用grails的单元测试中模拟springSecurityService

我已经使用了人与权威的域类是用户分别

作用作为每个项目的要求,我已经修改了我的User.groovy类和相同的代码如下:

class User { 
transient springSecurityService 

//Mandatory Fields 
String employeeId 
String firstName 
String lastName 
String password 
String emailId 

//Other Fields 
String mobileNumber 
String address 
String city 
String zipCode 

User manager 

static hasMany = [previousPasswords: String] 

boolean enabled = true 
boolean accountExpired 
boolean accountLocked 
boolean passwordExpired 

static transients = ['springSecurityService'] 

static constraints = { 
    employeeId blank: false, unique: true 
    firstName blank: false 
    lastName blank: false 
    password blank: false, password: true, validator: { val, obj -> 
     if(obj.previousPasswords) { 
      return !obj.previousPasswords.contains(encode(val.toUpperCase())) 
     } 
     return true 
    } 
    emailId blank: false, email: true 

    mobileNumber nullable: true 
    address nullable: true 
    city nullable: true 
    zipCode nullable: true 

    manager nullable: true 

    previousPasswords display: false, editable: false 
} 

static mapping = { 
    password column: '`password`' 
} 

Set<Role> getAuthorities() { 
    UserRole.findAllByUser(this).collect { it.role } as Set 
} 

def beforeInsert() { 
    previousPasswords = [encode(password.toUpperCase())] 
    encodePassword() 
} 

def beforeUpdate() { 
    if (isDirty('password')) { 
     previousPasswords << encode(password.toUpperCase()) 
     encodePassword() 
    } 
} 

protected String encode(String pwd) { 
    return springSecurityService.encodePassword(pwd) 
} 

protected void encodePassword() { 
    password = springSecurityService.encodePassword(password) 
} 
} 

我尝试编写单元测试来检查约束该单元类

我的一个测试看起来如下

void "test if employeeId can be blank or non-unique"() { 
    given: 

    def springSecurityService = mockFor(SpringSecurityService,true) 
    springSecurityService.encodePassword(){String pwd -> return null} 

//  def springSecurityServiceFactory = mockFor(SpringSecurityService,true) 
//  def mockSpringSecurityService = Mock(SpringSecurityService) 
//  mockSpringSecurityService.metaClass.encodePassword = {String password ->  return null} 
//  User.metaClass.encodePassword = { return null } 
//  User.metaClass.encode = {password -> return null } 
//  User.metaClass.getSpringSecurityService = { mockSpringSecurityService } 

    when: 'employeeId is blank' 
    def user = new User(employeeId: " ") 
    user.springSecurityService= springSecurityService 

    then: 'validation fails' 
    !user.validate() 
    user.errors.getFieldError("employeeId").codes.contains("nullable") 

    when: 'employeeId is unique' 
    user = new User(employeeId: "empId1", firstName: "f_name", lastName: "l_name", password: "password", emailId: "[email protected]") 
    user.springSecurityService= springSecurityService 

    then: 'validation succeeds' 
    user.validate() 

    user.save(flush: true, failOnError: true) 
    mockForConstraintsTests(User, [user]) 

    when: 'employeeId is non unique' 
    def user_2 = new User(employeeId: "empId1") 
    user_2.springSecurityService= springSecurityService  

    then: 'validation fails' 
    !user_2.validate() 
    user_2.errors.getFieldError("employeeId").codes.contains("unique") 
} 

我一直在尝试不同的方式来模拟springSecurityService,但都似乎失败。任何人都可以提出一种方法来嘲笑这项服务。

目前我收到此错误。

groovy.lang.MissingMethodException: No signature of method:     grails.test.GrailsMock.encodePassword() is applicable for argument types: (com.hp.bots.UserSpec$_$spock_feature_0_0_closure1) values: [[email protected]] 
at com.hp.bots.UserSpec.test if employeeId can be blank or non-unique(UserSpec.groovy:25) 

如果我尝试运行它作为集成测试(没有模拟),此测试也失败。我无法理解我出错的地方。

+0

您将不得不调用createMock来生成模拟并分配给用户实例,并在mockFor控件上记录需要的encodePassword – ajeeshpu

回答

1

我通常通过创建一个具有将被调用的函数的映射来模拟服务。我只会推荐这种方法,当有关服务只调用一个或两个简单函数时,这些调用就不需要进行验证/跟踪。在你的情况你给出条款可能是这样的:

def springSecurityService = [encodePassword: { password -> 
    return password 
}] 
+1

可能还需要验证对模拟上特定方法的调用,一个mockControl.verify更合适 – ajeeshpu

+0

这是真的,我会更新答案注意这一点。它的工作原理是 – rmlan

3

我想如果你有

springSecurityService.demand.encodePassword(){String pwd -> return null} 

更换

springSecurityService.encodePassword(){String pwd -> return null} 

user.springSecurityService= springSecurityService.createMock() (grails 2.3.7) 
and for user_2 

,你应该能够让这个测试运行。

你可以在这里看看更多的文档。 http://grails.org/doc/2.3.7/guide/testing.html

+0

。谢谢 – Rammohan

相关问题