Dax*_*xon 5 service grails junit unit-testing command-objects
我正在尝试测试具有数据绑定的Command对象的Controller.
命令对象注入了一个服务.
但是当我尝试测试命令对象时,从未找到注入的服务方法,因为它从未被"注入"
有没有办法在命令对象中模拟服务?
测试方法
void testLoginPasswordInvalid() {
mockRequest.method = 'POST'
mockDomain(User, [new User(login:"freddy", password:"realpassword")])
mockLogging(UserService) // userService mocked
MockUtils.prepareForConstraintsTests(LoginCommand)
def userService = new UserService()
def user = userService.getUser("freddy")//Gets called and returns the mockDomain
assert userService.getUser("freddy")//Passes
def cmd = new LoginCommand(login:"freddy", password:"letmein")
cmd.validate() // Fails (userService is nevr injected)
controller.login(cmd)
assertTrue cmd.hasErrors()
assertEquals "user.password.invalid", cmd.errors.password
assertEquals "/store/index", renderArgs.view
}
Run Code Online (Sandbox Code Playgroud)
找不到userService的getUser()方法
Cannot invoke method getUser() on null object
java.lang.NullPointerException: Cannot invoke method getUser() on null object
Run Code Online (Sandbox Code Playgroud)
码
调用控制器的登录方法,
def login = { LoginCommand cmd ->
if(request.method == 'POST') {
if(!cmd.hasErrors()){
session.user = cmd.getUser()
redirect(controller:'store')
}
else{
render(view:'/store/index', model:[loginCmd:cmd])
}
}else{
render(view:'/store/index')
}
}
Run Code Online (Sandbox Code Playgroud)
命令对象注入了"userService".
验证器调用此userService来查找用户
class LoginCommand {
def userService
String login
String password
static constraints = {
login blank:false, validator:{ val, cmd ->
if(!cmd.userService.getUser()){
return "user.not.found"
}
}
}
Run Code Online (Sandbox Code Playgroud)
userService.getUser()看起来像这样.
class UserService {
boolean transactional = true
User getUser(String login) {
return User.findByLogin(login)
}
}
Run Code Online (Sandbox Code Playgroud)
Joh*_*ham 11
使用Spring autowire-by-name完成服务注入.(Grep Grails源代码树autowire
可以找到一个很好的代码片段,你可以用它来让你在集成测试中为你的控制器自动装配.)这只能在集成测试中运行,其中有一个Spring应用程序上下文,它有可以使用的bean被注射
在单元测试中,你必须自己做,因为你的东西周围没有Spring-land.这可能是一种痛苦,但会带来一些好处:
1)注入模拟版本的服务很容易 - 例如,使用Expando
- 以更密切地指定控制器协作服务的行为,并允许您仅测试控制器逻辑而不是控制器和服务.(你当然可以在单元测试中做后者,但你可以选择如何连接它.)
2)它强制您明确控制器的依赖关系 - 如果您依赖它,您的测试将显示它.这使它们成为控制器行为的更好规范.
3)您只能模拟控制器所依赖的外部协作者.这有助于您的测试不那么脆弱 - 当事情发生变化时,不太可能需要更改.
简短的回答:你的测试方法需要一条cmd.userService = userService
线.
约翰所说的就是标记.一个例子可能是:
def mockUsers = [new User(login:"freddy", password:"realpassword")]
mockDomain(User, mockUsers)
def userService = [getUser:{String login -> mockUsers[0]}] as UserService
def cmd = new LoginCommand (/*arguments*/)
cmd.userService = userService
Run Code Online (Sandbox Code Playgroud)
您可以在http://groovy.codehaus.org/Groovy+Mocks查找模拟对象的其他方法
归档时间: |
|
查看次数: |
4072 次 |
最近记录: |