測試是軟件項目的重要組成部分,Spring Boot CLI當然沒有忽略測試。因為基於CLI的應用程序並未涉及傳統的構建系統,所以CLI提供了一個test
命令來運行測試。
在試驗test
命令前,你先要寫一個測試。測試可以放在項目中的任何位置。我建議將其與主要組件分開放置,最好放在一個子目錄裡。這個子目錄的名字隨意。我在這裡將其命名為tests:
$ mkdir tests
在tests目錄裡,創建一個名為ReadingListControllerTest.groovy的新Groovy腳本,編寫針對ReadingListController
的測試。代碼清單5-3是個簡單的測試,測試控制器能否正確處理HTTP GET
請求。
代碼清單5-3
ReadingListController
的Groovy測試
import org.springframework.test.web.servlet.MockMvc
import static
org.springframework.test.web.servlet.setup.MockMvcBuilders.*
import static org.springframework.test.web.servlet.request.
MockMvcRequestBuilders.*
import static org.springframework.test.web.servlet.result.
MockMvcResultMatchers.*
import static org.mockito.Mockito.*
class ReadingListControllerTest {
@Test
void shouldReturnReadingListFromRepository {
List<Book> expectedList = new ArrayList<Book>
expectedList.add(new Book(
id: 1,
reader: \"Craig\",
isbn: \"9781617292545\",
title: \"Spring Boot in Action\",
author: \"Craig Walls\",
description: \"Spring Boot in Action is ...\"
))
def mockRepo = mock(ReadingListRepository.class) ←---模擬 ReadingListRepository
when(mockRepo.findByReader(\"Craig\")).thenReturn(expectedList)
def controller =
new ReadingListController(readingListRepository: mockRepo)
MockMvc mvc = standaloneSetup(controller).build
mvc.perform(get(\"/\")) ←---執行並測試GET請求
.andExpect(view.name(\"readingList\"))
.andExpect(model.attribute(\"books\", expectedList))
}
}
如你所見,這就是個簡單的JUnit測試,使用了Spring的模擬MVC測試支持功能,對控制器發起GET
請求。最先設置的是ReadingListRepository
的一個模擬實現,它會返回一個包含單一Book
項的列表。隨後,測試創建了一個ReadingListController
實例,將模擬倉庫注入readingListRepository
屬性。最後,配置了一個MockMvc
對象,發起GET
請求,對期望的視圖名稱和模型內容進行斷言。
但是,此處運行測試要比說明測試更重要。使用CLI的test
命令,可以像下面這樣在命令行裡執行測試:
$ spring test tests/ReadingListControllerTest.groovy
本例中,我明確選中了ReadingListControllerTest
作為要運行的測試。如果tests/目錄裡有多個測試,你想要全部運行,可以在test
命令中指定目錄名:
$ spring test tests
如果你傾向於編寫Spock說明而非JUnit測試,那麼你一定會很高興,因為CLI的test
命令也可以運行Spock說明,代碼清單5-4的ReadingListControllerSpec
就演示了這一功能。
代碼清單5-4 測試
ReadingListController
的Spock說明
import org.springframework.test.web.servlet.MockMvc
import static
org.springframework.test.web.servlet.setup.MockMvcBuilders.*
import static org.springframework.test.web.servlet.request.
MockMvcRequestBuilders.*
import static org.springframework.test.web.servlet.result.
MockMvcResultMatchers.*
import static org.mockito.Mockito.*
class ReadingListControllerSpec extends Specification {
MockMvc mockMvc
List<Book> expectedList
def setup {
expectedList = new ArrayList<Book>
expectedList.add(new Book(
id: 1,
reader: \"Craig\",
isbn: \"9781617292545\",
title: \"Spring Boot in Action\",
author: \"Craig Walls\",
description: \"Spring Boot in Action is ...\"
))
def mockRepo = mock(ReadingListRepository.class) ←---模擬的ReadingListRepository
when(mockRepo.findByReader(\"Craig\")).thenReturn(expectedList)
def controller =
new ReadingListController(readingListRepository: mockRepo)
mockMvc = standaloneSetup(controller).build
}
def \"Should put list returned from repository into model\" {
when:
def response = mockMvc.perform(get(\"/\")) ←---執行GET請求
then:
response.andExpect(view.name(\"readingList\"))
.andExpect(model.attribute(\"books\", expectedList)) ←---測試結果
}
}
ReadingListControllerSpec
只是簡單地把 ReadingListControllerTest
從JUnit測試翻譯成了Spock說明。如你所見,它只是直白地表述了這麼一個過程。對「/
」出現GET
請求時,響應中應該包含名為readingList的視圖。模型裡的books
鍵所對應的就是期待的圖書列表。
Spock說明也可以通過spring test tests
來運行ReadingListControllerSpec
。運行方式和基於JUnit的測試如出一轍。
一旦寫好代碼,通過了全部測試,你就該部署項目了。讓我們來看看Spring Boot CLI是如何幫助產生一個可部署的產物的。