javascript
spring框架mvc框架_Spring的MVC测试框架入门–第1部分
spring框架mvc框架
最新推出的主要Spring框架是Spring MVC測試框架,Spring Guys聲稱它是“一流的JUnit支持,可通過流暢的API測試客戶端和服務器端Spring MVC代碼” 1 。 在這個博客以及下一個博客中,我將看一看Spring的MVC測試框架,并將其應用于我現有的一些示例代碼中,以弄清它是否能如其所愿。
該API通過兩種設置服務器端測試的方式進行了設計。 首先,它們帶有Spring上下文文件,其次,以編程方式沒有上下文文件。 Spring的Guy將該程序化方法稱為“獨立”模式。
以編程方式設置測試似乎更類似于單元測試,并且最好用于對特定的控制器類進行獨立于其協作者的單元測試。 另一方面,加載Spring上下文文件的操作實際上是集成測試,并且更適合端到端測試。
您可以在此處找到有關測試技術的博客的完整列表。
如果您像我一樣,那么您已經在使用現有的框架(例如Mockito或Easymock)來測試您的控制器。 通常的Mockito / Easymock方法是實例化您的控制器,注入模擬或存根依賴性,然后調用被測方法,注意返回值或驗證模擬方法調用。
Spring Mvc Test框架采用了與其他模擬框架不同的方法,因為它加載了Spring DispatcherServlet以模擬Web容器的操作。 然后將被測試的控制器加載到Spring上下文中,然后像在“現實生活中”那樣,由DispatcherServlet訪問。
這種方法的好處是,它允許您將控制器作為控制器而不是POJO進行測試。 這意味著將處理并考慮控制器的注釋,執行驗證并以正確的順序調用方法。
您是否同意這種方法,并取決于您對測試技術的看法。 如果您認為應該將測試的每個類/方法都隔離到第n個級別,并且每個測試都應完全原子化,那么這可能不適合您。 如果您比較實用,并且可以將測試控制器的好處看作是……一個控制器,那么此框架可能是您感興趣的。
與Mockito和Easymock的方法有所不同,缺點是代碼看起來與這些較老的,更成熟的技術不同。 它在很大程度上依賴于構建器模式來構造匹配器,請求構建器和處理程序,一旦掌握了這些,這一切就變得很有意義。 我懷疑使用構建器模式的動機是為了簡化模擬HttpServletRequest的設置以及對模擬HttpServletResponse對象的詢問,這從定義HttpServletResponse可能非常棘手。
在此博客中,我將看一下Spring API的編程/獨立技術,并將其與類似的基于Mockito的單元測試進行比較。
為了加快處理速度,我使用了Blue Peter方法“這是我之前準備的方法”,并從我的Facebook博客中獲取了FacebookPostsController ,我將為此編寫兩個單元測試類:第一個使用Mockito,另一個使用Spring Mvc測試API。
控制器代碼如下:
@Controller public class FacebookPostsController { private static final Logger logger = LoggerFactory .getLogger(FacebookPostsController.class); @Autowired private SocialContext socialContext; @RequestMapping(value = "posts", method = RequestMethod.GET) public String showPostsForUser(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception { String nextView; if (socialContext.isSignedIn(request, response)) { List<Post> posts = retrievePosts(); model.addAttribute("posts", posts); nextView = "show-posts"; } else { nextView = "signin"; } return nextView; } private List<Post> retrievePosts() { Facebook facebook = socialContext.getFacebook(); FeedOperations feedOps = facebook.feedOperations(); List<Post> posts = feedOps.getHomeFeed(); logger.info("Retrieved " + posts.size() + " posts from the Facebook authenticated user"); return posts; } }我不打算講這段代碼的背景,因為它可以在Facebook博客中找到 。 但是,總而言之,Facebook示例應用程序訪問用戶的Facebook帳戶并在示例應用程序中顯示其新聞提要。 為此, FacebookPostsController檢查SocialContext類,以確定用戶是否已登錄其Facebook帳戶。 如果用戶登錄到其Facebook帳戶,則控制器將檢索用戶的帖子并將其添加到模型中以進行顯示。 另一方面,如果用戶未登錄,則將他們定向到登錄頁面。
兩個單元測試類中的每一個都將包含三個公共方法:
我將依次檢查setup() , testShowPostsForUser_user_is_not_signed_in和testShowPostsForUser_user_is_signed_in 。
如您所料,測試testShowPostsForUser_user_is_not_signed_in和testShowPostsForUser_user_is_signed_in用于測試用戶登錄和未登錄其Facebook帳戶的情況。
“標準” Mockito測試
@Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); instance = new FacebookPostsController(); ReflectionTestUtils.setField(instance, "socialContext", socialContext); }設置代碼相當簡單,包含三個簡單步驟:
testShowPostsForUser_user_is_not_signed_in方法將模擬的SocialContext配置為在調用其isSignedIn()方法時返回false 。 這意味著剩下要做的就是斷言showPostsForUser(...)方法返回"signin"將用戶定向到登錄頁面。
@Test public void testShowPostsForUser_user_is_signed_in() throws Exception { when(socialContext.isSignedIn(request, response)).thenReturn(true); when(socialContext.getFacebook()).thenReturn(facebook); when(facebook.feedOperations()).thenReturn(feedOps); List<Post> posts = Collections.emptyList(); when(feedOps.getHomeFeed()).thenReturn(posts); String result = instance.showPostsForUser(request, response, model); verify(model).addAttribute("posts", posts); assertEquals("show-posts", result); }testShowPostsForUser_user_is_signed_in稍微復雜一些。 在將模擬的SocialContext配置為在調用其isSignedIn()方法時返回true ,還有另外四行代碼可確保從模擬Facebook提要中返回posts列表并將其添加到模擬Model 。 調用showPostsForUser(...)之后,需要完成兩個附加步驟:驗證模擬Model包含posts列表,并斷言showPostsForUser(...)的返回值為"show-posts" 。
接下來,Spring MVC Test框架代碼; 但是,在開始之前,您需要將以下依賴項添加到POM文件:
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${org.springframework-version}</version><scope>test</scope></dependency>Spring MVC測試
Spring MVC測試框架版本運行相同的兩個測試,但是方式不同……
@Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); FacebookPostsController instance = new FacebookPostsController(); ReflectionTestUtils.setField(instance, "socialContext", socialContext); mockMvc = MockMvcBuilders.standaloneSetup(instance).build(); } 如果看一下上面的代碼,就可以看到,就setup(...)而言,它看起來與上面的直接Mockito代碼非常相似。 像基于Mockito的測試一樣,第一步是使用初始化模擬對象
MockitoAnnotations.initMocks(this) ,然后創建一個FacebookPostsController的新實例,將模擬的SocialContext注入其中。 但是,這一次, FacebookPostsController狀態已降級為局部變量,因為設置的重點是創建Spring的MockMvc實例,該實例用于執行測試。 該mockMvc是通過調用創建MockMvcBuilders.standaloneSetup(instance).build()其中instance是FacebookPostsController對象,我們正在測試。
與Mockito版本類似, testShowPostsForUser_user_is_not_signed_in方法將模擬的SocialContext配置為在調用其isSignedIn()方法時返回false 。 這次,下一步是使用靜態方法創建一個稱為MockHttpServletRequestBuilder東西。
MockMvcRequestBuilders.get(...)和構建器模式。 這被傳遞到mockMVC.perform(...)方法中,在此方法中,該方法用于創建MockHttpServletRequest對象,該對象用于定義測試的起點。 在此測試中,我要做的只是傳遞"/posts" URL并將輸入設置為“ any”媒體類型。 您可以使用諸如contentType() , contextPath() , cookie()等方法配置許多其他請求對象屬性。有關更多信息,請查看Spring Javadoc中的MockHttpServletRequest
mockMvc.perform()方法返回一個ResultActions對象。 這似乎是實際MvcResult的包裝。 ResultsActions是一個便捷對象,用于以與JUnit的assertEquals(...)或Mockito的verify(..)方法相同的方式聲明測試結果。 在這種情況下,我正在檢查結果Http狀態是否正常(即200),并且下一個視圖將"signin" 。
此測試與僅Mockito版本之間的區別在于,您不是直接測試對測試實例的方法調用的結果; 您正在測試方法調用生成的HttpServletResponse對象。
@Test public void testShowPostsForUser_user_is_signed_in() throws Exception { HttpServletRequest request = anyObject(); HttpServletResponse response = anyObject(); when(socialContext.isSignedIn(request, response)).thenReturn(true); when(socialContext.getFacebook()).thenReturn(facebook); when(facebook.feedOperations()).thenReturn(feedOps); List<Post> posts = Collections.emptyList(); when(feedOps.getHomeFeed()).thenReturn(posts); mockMvc.perform(get("/posts").accept(MediaType.ALL)).andExpect(status().isOk()) .andExpect(model().attribute("posts", posts)) .andExpect(view().name("show-posts")); }testShowPostsForUser_user_is_signed_in方法的Spring Test版本與Mockito版本非常相似,該測試是通過將SocialContext.isSignedIn()方法配置為返回true以及feedOps.getHomeFeed()配置為返回posts列表來準備測試的。 此方法的Spring Mvc Test部分與上述testShowPostsForUser_user_is_not_signed_in版本幾乎相同,除了這次它使用andExpect(view().name("show-posts")檢查下一個視圖名稱為"show-posts"而不是"sign-in" andExpect(view().name("show-posts")我在這里使用的代碼樣式與我在上面使用的樣式有所不同,并且是Spring的Guy偏愛的樣式。如果您能在Github上找到更多這種樣式的示例,持有Spring MVC Showcase應用。
那么,您可以從此比較中得出什么結論? 公平地說,這不是真正的比較– Spring MVC Test API在建立標準Mockito技術的基礎上,采用了不同的方法,創建了一個框架,旨在僅在其本機運行時環境的模型中對Spring MVC控制器進行測試。 。
這對您是否有用,我會讓您決定。 它確實具有將控制器視為控制器而不是POJO的優點,這意味著它們已經過更徹底的測試。 從個人的角度來看,我喜歡加載Spring配置文件并將其用于集成測試的想法,這將在我的下一個博客中介紹。
- 1請參閱: http : //static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework
- 該博客的代碼可在GitHub上找到: https : //github.com/roghughe/captaindebug/tree/master/facebook
翻譯自: https://www.javacodegeeks.com/2013/07/getting-started-with-springs-mvc-test-framework-part-1.html
spring框架mvc框架
總結
以上是生活随笔為你收集整理的spring框架mvc框架_Spring的MVC测试框架入门–第1部分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 毅力的近义词 毅力有哪些近义词
- 下一篇: 跟踪反应流–将Spring Cloud