您好,登錄后才能下訂單哦!
本篇文章為大家展示了Spring MVC應用如何進行測試,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
Spring的依賴注入使得我們的代碼非常容易進行單元測試——@Controller
, @Service
,@Entity
等注解標注的類基本都是POJO(plain old Java object),也就是說很少依賴于Spring容器本身的API。我們可以非常容易地使用JUnit或TestNG編寫測試代碼。另一方面,對于三層架構的Spring Web應用(Controller, Service, DAO),使用Mock活Stub方法也能夠更好的來測試我們的代碼邏輯。例如Service層代碼的單元測試中,依賴的DAO(或Repository)對象都是根據應用測試需求Mock出來的,而不需要真正去訪問數據庫。
Spring Web測試
在對Spring Web應用中的@Controller
代碼進行單元測試的過程中,一般的方法是創建@Controller
對象,同時將它依賴的一些Mock對象——例如MockHttpServletRequest, MockHttpServletResponse(都由spring-test模塊提供,無需自己編寫)作為@Controller方法的參數。但是對于處理Web請求的@Controller代碼來說,僅僅測試Handler方法里的代碼是遠遠不夠的,對于一個處理HTTP請求的@Controller`,我們還需要測試:
@RequestMapping
路由是否正確@PathVariable
等@InitBinder
, @ModelAttribute
, @ExceptionHandler
等注解的方法或屬性計算過程上述過程貫穿于HTTP請求處理的生命周期中,所以對于Spring Web應用中@Controller
代碼單元測試的概念,應該做一些擴充——不僅僅局限于代碼本身,也要結合MVC框架中的各個處理過程。
本文接下來的內容代碼,都以Spring Boot為例,首先假設我們通過Spring Boot創建了一個最簡單的Web Mvc應用——包含了一個最簡單的Conroller,處理/users/{id}
對應的HTTP請求,返回值是id={id}
(通過String.format()
方法),那么可以為它創建如下測試代碼:
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SpringMvcTestDemoApplication.class) @WebAppConfiguration public class SpringMvcTestDemoApplicationTests { private MockMvc mockMvc; @Before public void init() { this.mockMvc = MockMvcBuilders.standaloneSetup(new UserController()).build(); } @Test public void getUserById() throws Exception { long id = 1; this.mockMvc.perform(get("/users/" + id)) .andExpect(status().isOk()) .andExpect(content().string("id=" + id)); } }
運行上述測試時,很容易從控制臺中的日志發現,SpringJUnit4ClassRunner
創建了一個Spring Web應用上下文,并且在其中進行了Web Mvc框架的配置——這里是注冊@RequestMapping
方法。接下來mockMvc.perform()
方法實際上向該Spring Web應用發起了一個HTTP請求:
/users/{id}
andExpect()
方法也就是測試中常用的Assert
status()
用于檢查返回狀態嗎,這里是200content()
用于檢查內容如果我們不小心將@RequestMapping
的路由路徑寫錯,那么這里運行的結果一定不會是status().isOk()
,這也就完成了對HTTP請求路由的測試。接下來我們將繼續探索MVC框架中的其他方面。
Mock Service
在Spring Web應用三層結構里,Controller層代碼通常會調用Service層代碼,例如:
@RestController public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/users/{id}", method = GET) public String get(@PathVariable("id") long id) { String username = userService.getUsername(id); return String.format("username=%s", username); } }
對UserController
進行單元測試需要排除Service代碼的影響,所以需要對Service進行Mock,這里我們使用Mockito框架,在Spring上下文中Mock一個UserService
對象:
@Configuration public class TestContext { @Bean public UserService userServiceMock() { return Mockito.mock(UserService.class); } }
同時通過Mockito
的API來MockUserService.getUsername(long id)
方法,@Controller
的測試代碼如下:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { SpringMvcTestDemoApplication.class, TestContext.class }) @WebAppConfiguration public class SpringMvcTestDemoApplicationTests { @Autowired UserService userService; @Autowired UserController controller; MockMvc mockMvc; @Before public void init() { this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } @Test public void getUserById() throws Exception { long id = 1L; String ricky = "Ricky"; Mockito.when(userService.getUsername(id)).thenReturn(ricky); this.mockMvc.perform(get("/users/" + id)) .andExpect(status().isOk()) .andExpect(content().string("username=" + ricky)); } }
由于需要進行依賴注入,所以UserService
和UserController
都使用@Autowired
注解。Mockito.when(userService.getUsername(id)).thenReturn(ricky)
;表明userService.getUsername()
方法的參數為1L時,返回值為"Ricky
",Mockito提供能很多強大的Mock API,更多用法請參考官方文檔。
測試REST API
當我們構建REST服務時,大多數情況會使用JSON作為數據交換格式,Spring MVC測試框架同樣提供了一種簡潔的方式對JSON結果進行斷言,假設現在有@Controller
如下:
@RequestMapping(value = "/users/{id}/json", method = GET) public User getUser(@PathVariable("id") long id) { String username = userService.getUsername(id); return new User(id, username); } static class User { public long id; public String username; //構造方法,Getter/Setter略 }
實際應用返回的JSON數據是:
{ "id": 1, "username": "Ricky" }
測試代碼可以這樣斷言:
@Test public void getUser() throws Exception { this.mockMvc.perform(get("/users/{id}/json", id).accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(id.intValue())) .andExpect(jsonPath("$.username").value(ricky)); }
$.id
, $.username
都是JsonPath提供的JSON表達式,可以通過jsonPath
、value()
等方法來輕松對JSON數據進行斷言而不需要自己編寫JSON文本處理。
上述內容就是Spring MVC應用如何進行測試,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。