2015-09-03 157 views
4

嘲笑springSecurityService我单元测试在内部创建一个用户实例一个Grails控制器的方法。用户域类使用了Spring安全插件的springSecurityService将其插入到数据库之前编码密码。如何在单元测试

有没有办法嘲笑,为了springSecurityService从我的单元测试,以摆脱错误的?

Failure: Create new individual member(MemberControllerSpec) 
| java.lang.NullPointerException: Cannot invoke method encodePassword() on null object 

请在下面找到我的单元测试。

@TestMixin(HibernateTestMixin) 
@TestFor(MemberController) 
@Domain([User, IndividualPerson]) 
class MemberControllerSpec extends Specification { 

void "Create new individual member"() { 

    given: 
    UserDetailsService userDetailsService = Mock(UserDetailsService) 
    controller.userDetailsService = userDetailsService 

    def command = new IndividualPersonCommand() 
    command.username = '[email protected]' 
    command.password = 'What ever' 
    command.firstname = 'Scott' 
    command.lastname = 'Tiger' 
    command.dob = new Date() 
    command.email = command.username 
    command.phone = '89348' 
    command.street = 'A Street' 
    command.housenumber = '2' 
    command.postcode = '8888' 
    command.city = 'A City' 

    when: 
    request.method = 'POST' 
    controller.updateIndividualInstance(command) 

    then: 
    view == 'createInstance' 

    and: 
    1 * userDetailsService.loadUserByUsername(command.username) >> null 

    and: 
    IndividualPerson.count() == 1 

    and: 
    User.count() == 1 

    cleanup: 
    IndividualPerson.findAll()*.delete() 
    User.findAll()*.delete() 
} 
} 
+0

用户如何域可以访问springSecurityService? – Yaro

回答

0

您可以使用此代码在User编码密码:

def beforeInsert() { 
    encodePassword() 
} 

def beforeUpdate() { 
    if (isDirty('password')) { 
     encodePassword() 
    } 
} 

protected void encodePassword() { 
    password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password 
} 

springSecurityService为null,encodePassword不叫和NPE不提高

嘲笑服务
+0

如果你改变你的用户类代码,铭记,这是改变类的行为,而不是metaClassing SpringSecurityService用于测试的持续时间,由Emmanuel如下所述。 – railsdog

+0

测试是如此奇妙的工具,允许检查您的代码功能和设计/实现失败。也许你只需要检查你的代码而不是强制测试。 –

3

的一种方式是使用Groovy的MetaClass

import grails.test.mixin.Mock 
import grails.plugin.springsecurity.SpringSecurityService 

... 
@Mock(SpringSecurityService) 
class MemberControllerSpec extends Specification { 

    def setupSpec() { 
     SpringSecurityService.metaClass.encodePassword = { password -> password } 
    } 

    def cleanupSpec() { 
     SpringSecurityService.metaClass = null 
    } 
.... 

在此示例中,拨打SpringSecurityService.encodePassword()的电话将以纯文本格式返回密码。

使用嘲笑的一种方法进行了讨论here

+0

这种方法对我不起作用。我的规格测试控制器而不是用户类。在现场后面,控制器方法创建一个用户实例。并且该用户实例没有注入安全服务(因为它是一个单元测试) – saw303