Grails中的单元测试用例嘲笑方法

时间:2014-12-09 09:37:00

标签: unit-testing grails groovy junit mocking

我试图在'LoginController'中为动作'passwordActive'编写一个单元测试用例。但我不确定要嘲笑的所有事情以及如何做到这一点。

    def passwordActive={
        log.error("Entering into Password Active")
        println "Password Active -- Params =  "+params

        String contextPath = request.contextPath
        String username = null              
        User user = null

    try{

            if (params.username != null && params.username.trim().length() > 0) {
            username = params.username
            user = User.findByUsername(username)
            }

            if (user == null) {
                log.error("USER not found.")                
                flash.errorLogin = "Username is incorrect"
                redirect(action:"auth") 
                return          
             }else if(user.password != params.password){
                log.error("USER password is wrong..")
                flash.errorLogin = "Please enter valid password.."
                redirect(action:"auth")
                return
             }else if (!user.active) {
                log.error("USER is inactive.")              
                flash.errorLogin = "User in Inactive"
                redirect(action:"auth") 
                return          
            }

            session["userid"] = user.id

            String userRole = user.authority.authority
            String url = contextPath + "/" + userRole           
            println "URL = "+url                
            redirect(url: url, method: 'post', params: params)      
            return  
       }
       catch(Exception e){
        println e.printStackTrace()
       }

    log.error("Exit into Password Active")

    }

我想写一个不存在用户名的测试用例。在这种情况下,flash消息应该有消息“用户名不正确”,我可以断言它。 这里应该嘲笑所有事情以及如何做到这一点。能否请您解释一下使用一个小例子(最好与上面的代码相关,以便我理解)

1 个答案:

答案 0 :(得分:0)

编写自己的安全实现是一个非常糟糕的主意。我建议你看看Spring Security插件如何用于教育目的,然后只使用该插件 - 它成熟,灵活且易于设置。

出于上述教育目的,让我们看看我们如何使用一种方法来模拟上面的代码,这种方法与Spring Security的工作方式大致相同:您可以将用户查找移动到服务/ bean中,因为控制器并不意味着包含任何“业务”逻辑。说这样的话:

class UserProviderService {
    User findUser(String username) {
        User.findByUsername(username)
    }
}

在控制器中,您可以将其作为依赖项(def userProviderService)注入,然后您可以在其上调用自己的函数,例如: userProviderService.findUser(username)。在正常操作期间,Grails会将UserProviderService注入控制器,而在单元测试中,您可以随意模拟它(例如controller.userProviderService = [ findByUsername: { -> return null } ],例如,如果您想测试未知用户的控制器响应。

类似于密码比较,您将使用passwordService来实现密码散列,比较等等,您可以在每次测试之前模拟其响应。请注意,如果您关心安全性并且很容易再次陷入困境,那么这个东西也不是一件容易的事情:不要自己动手!

构建代码的方式决定了测试它的难易程度。当然你可能会混淆User.metaclass并左右覆盖方法,但这种方法通常证明非常脆弱。通过拆分代码,您可以让您的生活更轻松!如何构建代码以使其可测试绝对是您通过经验学习的东西,所以请继续思考它!