2010-11-03 65 views
1

直从104页“权威指南Grails的(第二版)”:的Grails 1.3.5控制器测试空命令对象

void testLoginUserNotFound() { 
    mockRequest.method = "POST" 
    mockDomain(User) 
    MockUtils.prepareForConstraintsTests(LoginCommand) 
    def cmd = new LoginCommand(login:"fred", password:"letmein") 

    cmd.validate() 
    controller.login(cmd) 

    assertTrue cmd.hasErrors() 
    assertEquals "user.not.found", cmd.errors.login 
    assertEquals "/store/index", renderArgs.view 
} 

当此测试运行时,它失败:

junit.framework.AssertionFailedError: junit.framework.AssertionFailedError: null 

...我跟踪到的“cmd”参考在那个点上是空的。在调用action.login之前,cmd是有效的并且被填充,之后它为空。

如何测试命令对象?

+1

[-1]我是对在部分(* * cmd不为空**),并且在其他部分中部分错误。 - 但是,我已经识别,下载并更正了这些样本,以便在实际的单元测试案例中**。 - 我期望一些参与和由此产生的回应。 - 被抛弃的问题。 – robbbert 2010-11-24 21:59:06

回答

0

cmd不是null;但是,assertTrue会抛出AssertionFailedErrornull消息。要么提供默认消息(assertTrue "default message", cmd.hasErrors()),要么只提供状态assert cmd.hasErrors()

因此,让我们来看看为什么cmd.hasErrors()返回false。 - 这是因为自定义验证程序不会返回false,而是根据“Groovy Truth”计算出的一些字符串,它的计算结果为true。 (在那里,Grails的API似乎已经改变,因为这本书已经出版。)

LoginCommand类,改变

login blank:false, validator:{ val, cmd -> 
    if(!cmd.user) 
     return "user.not.found" 
} 

login blank:false, validator:{ val, cmd -> 
    if(!cmd.user) 
     return false 
} 

然后,错误代码会“LoginCommand.login.validator”。
如果您需要自定义错误代码,你可以自己add an error object(不返回任何东西),像这样:

login blank:false, validator:{ val, cmd -> 
    if(!cmd.user) 
     cmd.errors.rejectValue('login', 'user.not.found') 
} 

P.S:您shouldn't useMockUtils类,直接,而是extend GrailsUnitTest。另外,MockUtils.prepareForConstraintsTests(Class)已弃用;而且,它不适合命令对象。 - 使用mockForConstraintsTests(Class)方法,而不是从GrailsUnitTest继承。

0

我使用在控制器单元测试此方法,以增加额外的管道为命令对象:

private def invoke(String action) { 
    def types = controller."$action".parameterTypes 
    if (types && types.length == 1) { 
     Class cmdClass = types[0] 
     mockCommandObject(cmdClass) 
     def cmd = cmdClass.newInstance() 
     controller.params.each{ key, value -> 
     try{ cmd."$key" = value } catch(MissingPropertyException ex){} 
     } 
     cmd.validate() 
     controller."$action"(cmd) 
    } else { 
     controller."$action"() 
    } 
    } 

测试看起来像这样:

setup: 
    controller.params.contractNum = "invalid" 


    when: 
    invoke "lookup"