MockMvc vs 端到端測試

MockMvc 基於 spring-test 模組中的 Servlet API mock 實現構建,不依賴於正在執行的容器。因此,與使用實際客戶端和執行中伺服器進行的完整的端到端整合測試相比,存在一些差異。

對此最簡單的理解方式是,從一個空白的 MockHttpServletRequest 開始。你向其中新增什麼,請求就會變成什麼樣。可能讓你感到意外的是,預設情況下沒有上下文路徑;沒有 jsessionid cookie;沒有轉發、錯誤或非同步分派;因此也沒有實際的 JSP 渲染。相反,“轉發”和“重定向”的 URL 被儲存在 MockHttpServletResponse 中,可以透過期望進行斷言。

這意味著,如果你使用 JSP,可以驗證請求被轉發到了哪個 JSP 頁面,但不會渲染 HTML。換句話說,JSP 沒有被呼叫。然而請注意,所有其他不依賴於轉發的渲染技術,例如 Thymeleaf 和 Freemarker,都會像預期一樣將 HTML 渲染到響應體中。透過 `@ResponseBody` 方法渲染 JSON、XML 和其他格式也是如此。

或者,你可以考慮使用 `@SpringBootTest` 的 Spring Boot 提供的完整端到端整合測試支援。請參閱Spring Boot 參考指南

每種方法都有其優缺點。Spring MVC Test 中提供的選項是在經典單元測試到完整整合測試這一範圍內的不同停靠點。可以肯定的是,Spring MVC Test 中的任何選項都不屬於經典單元測試的範疇,但它們離經典單元測試更近一些。例如,你可以透過將模擬服務注入到控制器中來隔離 Web 層,在這種情況下,你僅透過 DispatcherServlet 測試 Web 層,但使用實際的 Spring 配置,就像你隔離測試資料訪問層而不依賴於其上層一樣。此外,你還可以使用獨立設定,一次只關注一個控制器,並手動提供使其正常工作所需的配置。

使用 Spring MVC Test 的另一個重要區別在於,從概念上講,這類測試是伺服器端測試,因此你可以檢查使用了哪個處理器,異常是否由 HandlerExceptionResolver 處理,模型的內容是什麼,有哪些繫結錯誤,以及其他細節。這意味著編寫期望更容易,因為伺服器不是一個不透明的黑箱,這與透過實際 HTTP 客戶端進行測試時不同。這通常是經典單元測試的一個優點:更容易編寫、理解和除錯,但它並不能取代完整整合測試的需求。同時,重要的是不要忽視響應是最重要的檢查內容這一事實。簡而言之,即使在同一個專案中,也有多種測試風格和策略的空間。