讀古今文學網 > Spring Boot實戰 > 5.3 用CLI運行測試 >

5.3 用CLI運行測試

測試是軟件項目的重要組成部分,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是如何幫助產生一個可部署的產物的。