單元測試

相依性注入應使您的程式碼比傳統 J2EE / Java EE 開發更少地依賴容器。構成您的應用程式的 POJO 應該可以在 JUnit 或 TestNG 測試中進行測試,物件是使用 new 運算子實例化的,而無需 Spring 或任何其他容器。您可以搭配使用模擬物件 (結合其他有價值的測試技術) 以隔離方式測試您的程式碼。如果您遵循 Spring 的架構建議,程式碼庫的乾淨分層和組件化將有助於更輕鬆地進行單元測試。例如,您可以透過 Stubbing 或模擬 DAO 或儲存庫介面來測試服務層物件,而無需在執行單元測試時存取持久性資料。

真正的單元測試通常執行速度極快,因為沒有執行階段基礎架構需要設定。強調真正的單元測試作為您開發方法的一部分可以提高您的生產力。您可能不需要測試章節的此部分來協助您為基於 IoC 的應用程式編寫有效的單元測試。但是,對於某些單元測試情境,Spring Framework 提供了模擬物件和測試支援類別,本章將對其進行說明。

模擬物件

Spring 包含許多專用於模擬的套件

環境

org.springframework.mock.env 套件包含 EnvironmentPropertySource 抽象的模擬實作 (請參閱Bean 定義設定檔PropertySource 抽象)。MockEnvironmentMockPropertySource 對於開發程式碼的容器外測試非常有用,這些程式碼依賴於環境特定的屬性。

Servlet API

org.springframework.mock.web 套件包含一組全面的 Servlet API 模擬物件,這些物件對於測試 Web Context、控制器和篩選器非常有用。這些模擬物件的目標是用於 Spring 的 Web MVC Framework,並且通常比動態模擬物件 (例如 EasyMock) 或替代 Servlet API 模擬物件 (例如 MockObjects) 更方便使用。

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

MockMvc 建構在模擬 Servlet API 物件之上,為 Spring MVC 提供整合測試 Framework。請參閱MockMvc

Spring Web Reactive

org.springframework.mock.http.server.reactive 套件包含 ServerHttpRequestServerHttpResponse 的模擬實作,用於 WebFlux 應用程式。org.springframework.mock.web.server 套件包含一個模擬 ServerWebExchange,它依賴於這些模擬請求和回應物件。

MockServerHttpRequestMockServerHttpResponse 都從與伺服器特定實作相同的抽象基底類別擴充而來,並與它們共用行為。例如,模擬請求一旦建立就不可變,但是您可以使用 ServerHttpRequest 中的 mutate() 方法來建立修改後的實例。

為了使模擬回應正確實作寫入契約並傳回寫入完成處理常式 (即 Mono<Void>),預設情況下,它使用具有 cache().then()Flux,這會緩衝資料並使其可用於測試中的斷言。應用程式可以設定自訂寫入函式 (例如,測試無限串流)。

WebTestClient 建構在模擬請求和回應之上,以提供對在沒有 HTTP 伺服器的情況下測試 WebFlux 應用程式的支援。用戶端也可以用於具有執行中伺服器的端對端測試。

單元測試支援類別

Spring 包含許多可以協助進行單元測試的類別。它們分為兩類

一般測試公用程式

org.springframework.test.util 套件包含多種通用公用程式,用於單元測試和整合測試。

AopTestUtils 是 AOP 相關公用程式方法的集合。您可以使用這些方法來取得對隱藏在一個或多個 Spring Proxy 後面的底層目標物件的參考。例如,如果您已使用 EasyMock 或 Mockito 等程式庫將 Bean 組態為動態模擬,並且模擬包裝在 Spring Proxy 中,則您可能需要直接存取底層模擬,以在其上組態預期並執行驗證。對於 Spring 的核心 AOP 公用程式,請參閱 AopUtilsAopProxyUtils

ReflectionTestUtils 是基於反射的公用程式方法的集合。您可以在測試情境中使用這些方法,在這些情境中,您需要變更常數的值、設定非 public 欄位、調用非 public Setter 方法,或在測試應用程式程式碼時調用非 public 組態或生命週期回呼方法,以用於以下用例

  • ORM Framework (例如 JPA 和 Hibernate),它們允許 privateprotected 欄位存取,而不是網域實體中屬性的 public Setter 方法。

  • Spring 對註解 (例如 @Autowired@Inject@Resource) 的支援,這些註解為 privateprotected 欄位、Setter 方法和組態方法提供相依性注入。

  • 使用 @PostConstruct@PreDestroy 等註解進行生命週期回呼方法。

TestSocketUtils 是一個簡單的公用程式,用於在 localhost 上尋找可用的 TCP 連接埠,以用於整合測試情境。

TestSocketUtils 可用於在可用的隨機連接埠上啟動外部伺服器的整合測試中。但是,這些公用程式不保證給定連接埠的後續可用性,因此不可靠。建議您依賴伺服器在它選擇或由作業系統指派的隨機暫時連接埠上啟動的能力,而不是使用 TestSocketUtils 來尋找伺服器的可用本機連接埠。若要與該伺服器互動,您應該查詢伺服器以取得它目前正在使用的連接埠。

Spring MVC 測試公用程式

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

單元測試 Spring MVC 控制器
若要將您的 Spring MVC Controller 類別作為 POJO 進行單元測試,請使用 ModelAndViewAssert,並結合 Spring 的 Servlet API 模擬中的 MockHttpServletRequestMockHttpSession 等。若要徹底整合測試您的 Spring MVC 和 REST Controller 類別以及您的 Spring MVC 的 WebApplicationContext 組態,請改用 MockMvc