單元測試

依賴注入應該讓你的程式碼對容器的依賴程度低於傳統的 J2EE / Java EE 開發。組成你應用的 POJO 應該可以在 JUnit 或 TestNG 測試中進行測試,透過使用 new 運算子例項化物件,而無需 Spring 或任何其他容器。你可以使用 mock 物件(結合其他有價值的測試技術)來隔離地測試你的程式碼。如果你遵循 Spring 的架構建議,由此產生的清晰分層和程式碼庫元件化有助於更輕鬆地進行單元測試。例如,你可以透過 stub 或 mock DAO 或 repository 介面來測試服務層物件,而無需在執行單元測試時訪問持久化資料。

真正的單元測試通常執行速度非常快,因為不需要設定執行時基礎設施。將真正的單元測試作為開發方法的一部分來強調可以提高你的生產力。你可能不需要測試章節的這一部分來幫助你為基於 IoC 的應用程式編寫有效的單元測試。然而,對於某些單元測試場景,Spring Framework 提供了 mock 物件和測試支援類,本章對此進行了描述。

Mock 物件

Spring 包含了許多專門用於 mock 的包

環境

org.springframework.mock.env 包包含了 EnvironmentPropertySource 抽象的 mock 實現(參見 Bean 定義 ProfilePropertySource 抽象)。MockEnvironmentMockPropertySource 對於開發依賴於特定環境屬性的程式碼的容器外測試非常有用。

Servlet API

org.springframework.mock.web 包包含了一整套 Servlet API mock 物件,這些物件對於測試 web 上下文、控制器和過濾器非常有用。這些 mock 物件主要用於 Spring 的 Web MVC 框架,並且通常比動態 mock 物件(例如 EasyMock)更方便使用。

自 Spring Framework 6.0 起,org.springframework.mock.web 中的 mock 物件基於 Servlet 6.0 API。

MockMvc 基於 mock Servlet API 物件構建,為 Spring MVC 提供了一個整合測試框架。參見 MockMvc

Spring Web Reactive

org.springframework.mock.http.server.reactive 包包含了用於 WebFlux 應用程式的 ServerHttpRequestServerHttpResponse 的 mock 實現。org.springframework.mock.web.server 包包含了依賴於這些 mock 請求和響應物件的 mock ServerWebExchange

MockServerHttpRequestMockServerHttpResponse 都繼承自與伺服器特定實現相同的抽象基類,並與它們共享行為。例如,mock 請求一旦建立就不可變,但你可以使用 ServerHttpRequest 中的 mutate() 方法建立一個修改後的例項。

為了使 mock 響應能夠正確實現寫入契約並返回寫入完成控制代碼(即 Mono<Void>),它預設使用帶有 cache().then()Flux,這會緩衝資料並使其在測試中可用於斷言。應用程式可以設定自定義寫入函式(例如,用於測試無限流)。

WebTestClient 基於 mock 請求和響應構建,為測試 WebFlux 應用提供支援,而無需 HTTP 伺服器。該客戶端也可用於與執行中的伺服器進行端到端測試。

單元測試支援類

Spring 包含許多有助於單元測試的類。它們分為兩類:

通用測試工具

org.springframework.test.util 包包含了一些用於單元測試和整合測試的通用工具類。

AopTestUtils 是一系列與 AOP 相關的工具方法集合。你可以使用這些方法獲取隱藏在一個或多個 Spring 代理背後的底層目標物件的引用。例如,如果你使用 EasyMock 或 Mockito 等庫將一個 bean 配置為動態 mock,並且該 mock 被包裝在 Spring 代理中,你可能需要直接訪問底層 mock 來配置其期望並執行驗證。對於 Spring 的核心 AOP 工具類,請參見 AopUtilsAopProxyUtils

ReflectionTestUtils 是一系列基於反射的工具方法集合。在以下應用場景中測試應用程式碼時,如果你需要更改常量的值、設定非 public 欄位、呼叫非 public setter 方法或呼叫非 public 配置或生命週期回撥方法,可以使用這些方法:

  • 支援 privateprotected 欄位訪問(而非 public setter 方法)來訪問領域實體屬性的 ORM 框架(例如 JPA 和 Hibernate)。

  • Spring 對註解(例如 @Autowired@Inject@Resource)的支援,這些註解為 privateprotected 欄位、setter 方法和配置方法提供依賴注入。

  • 使用 @PostConstruct@PreDestroy 等註解作為生命週期回撥方法。

TestSocketUtils 是一個簡單的工具類,用於在整合測試場景中查詢 localhost 上可用的 TCP 埠。

TestSocketUtils 可用於在可用隨機埠上啟動外部伺服器的整合測試。然而,這些工具並不能保證給定埠後續仍然可用,因此是不可靠的。建議不要使用 TestSocketUtils 來為伺服器查詢可用的本地埠,而是依賴伺服器自行選擇或由作業系統分配的隨機臨時埠啟動。要與該伺服器互動,應查詢伺服器當前正在使用的埠。

Spring MVC 測試工具

org.springframework.test.web 包包含 ModelAndViewAssert,你可以將其與 JUnit、TestNG 或任何其他測試框架結合使用,用於處理 Spring MVC ModelAndView 物件的單元測試。

單元測試 Spring MVC 控制器
要將你的 Spring MVC Controller 類作為 POJO 進行單元測試,請結合使用 ModelAndViewAssert 和 Spring 的 Servlet API mocks 中的 MockHttpServletRequestMockHttpSession 等。要對你的 Spring MVC 和 REST Controller 類以及 Spring MVC 的 WebApplicationContext 配置進行全面的整合測試,請改為使用 MockMvc