2010-11-03 52 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"