2014-04-01 129 views
1

我有一個控制器類與此代碼:的Grails /斯波克單元測試

List<MultipartFile> files = [] 
List<String> convertedContents = [] 
def convertedFiles = [:] 

try { 
    params.myFile.each { 
     if (((MultipartFile) it.value).empty) { 
      throw new NoUploadedFileException('Break .each closure due to empty input.') 
     } 
     files.add((MultipartFile) it.value) 
    } 
} catch (NoUploadedFileException e) { 
    redirect uri: request.getHeader('referer') 
    return 
} 

convertedContents = converterService.convertToBase64(files) 
(code omitted) 

我也有一個測試:

def "sampleTest"() {  
    when: 
     controller.sendFax() 
    then: 
     thrown(NoUploadedFileException) 
    response.redirectedUrl == 'index.gsp' 
} 

我試圖測試的是,我的控制器將拋出當沒有文件上傳並且點擊提交按鈕時出現「NoUploadedFileException」。

這是錯誤:

Running 1 unit test... 1 of 1 
| Failure: sampleTest(com.synacy.HomeControllerSpec) 
| Expected exception com.synacy.NoUploadedFileException, but got 
java.lang.NullPointerException 
at org.spockframework.lang.SpecInternals.thrownImpl(SpecInternals.java:79) 
at com.synacy.HomeControllerSpec.throws NoUploadedFileException and returns to the 
same page when no file is uploaded(HomeControllerSpec.groovy:36) 
Caused by: java.lang.NullPointerException: Cannot invoke method convertToBase64() on 
null object 
at com.synacy.HomeController.sendFax(HomeController.groovy:43) 
at com.synacy.HomeControllerSpec.sampleTest(HomeControllerSpec.groovy:33) 

看來,它是不會通過try-catch塊,或者如果是,執行不工作。

+1

也許'params.myFile.each'與'NullPointerException'失敗,因爲你沒有發送任何參數? –

+0

NullPointerException指向try-catch塊後面的convertToBase64()方法。如果MyFile爲空或空,我的catch塊應該能夠處理它。 P.S.我試着檢查「== null || isEMpty()」來確認。問題仍然存在 – Marz

+3

如果'params.myFile'爲空,那麼'each' closure將不會運行 –

回答

0

你應該嘲笑你的服務,讓您的測試應該是這樣的:

@TestFor(MultipleFileUploadController) 
@Mock([ConverterService]) 
class MultipleFileUploadControllerSpec extends Specification { 
... 
} 

但測試不會通過,因爲你處理NoUploadedFileException控制器中,所以它不會在測試中的任何地方捕獲,所以你應該失敗,

Expected exception com.stackoverflow.NoUploadedFileException, but no exception was thrown 

從測試中刪除線拋出(NoUploadedFileException)

+0

但這是測試的重點。它應該模擬用戶點擊「提交」按鈕而不上傳任何文件,然後觸發控制器的方法並返回NoUploadedFileException的情況。然後它會被捕獲,然後渲染或重定向用戶回到頁面。 – Marz

+0

如果沒有選擇的文件params.myFile.each不會執行,因爲params.myFile將爲空列表或null,但eqch爲null安全 –

+0

我的測試用例應該是什麼?附:當用戶單擊沒有任何上傳文件的「提交」按鈕時,params.myFile(它是輸入框的名稱)的大小()仍爲1,並帶有CommonsMultipartFile值,但它是空的。我不知道爲什麼,但是這是我所推斷出的隔離方法。 – Marz

0

對於單元測試,在任何設置:或當:你必須創建環境控制器內行事

填充與任何頁眉/ PARAMS請求/數據是適當的 - 頭,參數,有效載荷,不管。根據需要設置適當的grails應用程序配置。

你的NPE說你沒有擊中你想要測試的控制器代碼。 NPE是因爲您的控制器沒有分配/注入converterservice(這是一個單元測試)。你沒有爲你的控制器設置任何參數,所以你沒有輸入你的每個代碼塊。

也許controller.params.myFile =新MultipartFile()//只是猜測這裏

從我的測試(我想測試JSON響應,所以我必須要適當地格式化要求)一個

縮寫示例:

@TestFor(DirectoryController) 
@Mock([SpringSecurityService,ConfigurationService,ConfigurationDomain,EntryDomain]) 
class DirectoryControllerSpec extends Specification 
    def "test getDirectorySources"() { 
     setup: 
     // not testing authentication, so just return true 
     SpringSecurityUtils.metaClass.static.ifAllGranted = { String role -> 
      return true 
     } 
     // mock the data to be returned from the configurationService call 
     def configuration = new ConfigurationDomain(id:2,name:'Mock Config',entries:[]) 
     def typeEntry = new EntryDomain(key:'ldap01.type',value:'ad') 
     configuration.entries << typeEntry 
     def nameEntry = new EntryDomain(key:'ldap01.name',value:'LDAP01') 
     configuration.entries << nameEntry 
     // mock the configurationService 
     def mockConfigurationService = mockFor(ConfigurationService, true) // loose mock 
     mockConfigurationService.demand.getConfigurationById() { Long id -> 
      return configuration 
     } 
     controller.configurationService = mockConfigurationService.createMock() 

     when: 
     // setup the request attributes 
     request.setContentType('application/json') 
     request.method = 'GET' 
     request.addHeader('Accept','application/json') 
     controller.params.id = "2" 
     controller.getDirectorySources() 

     then: 
     response.getText() == '{"sources":[{"key":"ldap01","name":"LDAP01","type":"ad"}]}' 

     cleanup: 
     // reset the metaClass 
     SpringSecurityUtils.metaClass = null 
    } 
} 

模擬控制器使用的任何服務;你沒有測試你的converterService,所以應該被嘲笑,並返回一個已知值,以便你知道控制器應該做什麼來響應服務返回的數據。

總之,在單元測試中,您應該控制所有不在直接控制器代碼中的東西。

0

嘗試嘲笑你的測試類如上面爲您服務:

@TestFor(MultipleFileUploadController)

@Mock([ConverterService])

這將解決你的問題,因爲斯波克會嘲笑ConverterService類爲你,你可以調用它的方法。請記住,您的方法中使用的每個域和服務都應在您的測試中嘲笑。希望它會有所幫助。