我试图在'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消息应该有消息“用户名不正确”,我可以断言它。 这里应该嘲笑所有事情以及如何做到这一点。能否请您解释一下使用一个小例子(最好与上面的代码相关,以便我理解)
答案 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
并左右覆盖方法,但这种方法通常证明非常脆弱。通过拆分代码,您可以让您的生活更轻松!如何构建代码以使其可测试绝对是您通过经验学习的东西,所以请继续思考它!