乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Spring MVC測試框架詳解

       taitanewtopqjh 2015-01-31

      隨著RESTful Web Service的流行,測試對外的Service是否滿足期望也變的必要的。從Spring 3.2開始Spring了Spring Web測試框架,如果版本低于3.2,請使用spring-test-mvc項目(合并到spring3.2中了)。

       

      Spring MVC測試框架提供了對服務(wù)器端和客戶端(基于RestTemplate的客戶端)提供了支持。

       

      對于服務(wù)器端:在Spring 3.2之前,我們測試時一般都是直接new控制器,注入依賴,然后判斷返回值。但是我們無法連同Spring MVC的基礎(chǔ)設(shè)施(如DispatcherServlet調(diào)度、類型轉(zhuǎn)換、數(shù)據(jù)綁定、攔截器等)一起測試,另外也沒有現(xiàn)成的方法測試如最終渲染的視圖(@ResponseBody生成的JSON/XML、JSP、Velocity等)內(nèi)容是否正確。從Spring 3.2開始這些事情都可以完成了。而且可以測試完整的Spring MVC流程,即從URL請求到控制器處理,再到視圖渲染都可以測試。

       

      對于客戶端:不需要啟動服務(wù)器即可測試我們的RESTful 服務(wù)。

       

      1 服務(wù)器端測試

      我的環(huán)境:JDK7、Maven3、spring4、Servlet3

       

      首先添加依賴

      如下是spring-context和spring-webmvc依賴:

      Java代碼  收藏代碼
      1. <dependency>  
      2.     <groupId>org.springframework</groupId>  
      3.     <artifactId>spring-context</artifactId>  
      4.     <version>${spring.version}</version>  
      5. </dependency>  
      6.   
      7. <dependency>  
      8.     <groupId>org.springframework</groupId>  
      9.     <artifactId>spring-webmvc</artifactId>  
      10.     <version>${spring.version}</version>  
      11. </dependency>  

      版本信息:<spring.version>4.0.0.RELEASE</spring.version>

       

      如下是測試相關(guān)的依賴(junit、hamcrest、mockito、spring-test):

      Java代碼  收藏代碼
      1. <dependency>  
      2.     <groupId>junit</groupId>  
      3.     <artifactId>junit</artifactId>  
      4.     <version>${junit.version}</version>  
      5.     <scope>test</scope>  
      6. </dependency>  
      7.   
      8. <dependency>  
      9.     <groupId>org.hamcrest</groupId>  
      10.     <artifactId>hamcrest-core</artifactId>  
      11.     <version>${hamcrest.core.version}/version>  
      12.     <scope>test</scope>  
      13. </dependency>  
      14. <dependency>  
      15.     <groupId>org.mockito</groupId>  
      16.     <artifactId>mockito-core</artifactId>  
      17.     <version>${mockito.core.version}</version>  
      18.     <scope>test</scope>  
      19. </dependency>  
      20.   
      21. <dependency>  
      22.     <groupId>org.springframework</groupId>  
      23.     <artifactId>spring-test</artifactId>  
      24.     <version>${spring.version}</version>  
      25.     <scope>test</scope>  
      26. </dependency>  
      版本信息:<junit.version>4.11</junit.version>、<hamcrest.core.version>1.3</hamcrest.core.version>、<mockito.core.version>1.9.5</mockito.core.version>

      然后準備測試相關(guān)配置

      實體:

      Java代碼  收藏代碼
      1. package com.sishuok.mvc.entity;  
      2. import java.io.Serializable;  
      3. public class User implements Serializable {  
      4.     private Long id;  
      5.     private String name;  
      6.     //省略getter/setter等  
      7. }  

       

      控制器:

      Java代碼  收藏代碼
      1. package com.sishuok.mvc.controller;  
      2. //省略import  
      3. @Controller  
      4. @RequestMapping("/user")  
      5. public class UserController {  
      6.   
      7.     @RequestMapping("/{id}")  
      8.     public ModelAndView view(@PathVariable("id") Long id, HttpServletRequest req) {  
      9.         User user = new User();  
      10.         user.setId(id);  
      11.         user.setName("zhang");  
      12.   
      13.         ModelAndView mv = new ModelAndView();  
      14.         mv.addObject("user", user);  
      15.         mv.setViewName("user/view");  
      16.         return mv;  
      17.     }  
      18. }  

       

      XML風格配置:

      spring-config.xml:加載非web層組件 

      Java代碼  收藏代碼
      1. <?xml version="1.0" encoding="UTF-8"?>  
      2. <beans xmlns="http://www./schema/beans"  
      3.        xmlns:xsi="http://www./2001/XMLSchema-instance"  
      4.        xmlns:context="http://www./schema/context"  
      5.        xsi:schemaLocation="  
      6.        http://www./schema/beans http://www./schema/beans/spring-beans.xsd  
      7.        http://www./schema/context http://www./schema/context/spring-context.xsd  
      8.        ">  
      9.     <!-- 通過web.xml中的 org.springframework.web.context.ContextLoaderListener 加載的  -->  
      10.     <!-- 請參考 http://jinnianshilongnian./blog/1602617  -->  
      11.     <context:component-scan base-package="com.sishuok.mvc">  
      12.         <context:exclude-filter type="annotation" ="org.springframework.stereotype.Controller"/>  
      13.     </context:component-scan>  
      14. </beans>  

       

      spring-mvc.xml:加載和配置web層組件 

      Java代碼  收藏代碼
      1. <?xml version="1.0" encoding="UTF-8"?>  
      2. <beans xmlns="http://www./schema/beans"  
      3.        xmlns:xsi="http://www./2001/XMLSchema-instance"  
      4.        xmlns:context="http://www./schema/context"  
      5.        xmlns:mvc="http://www./schema/mvc"  
      6.        xsi:schemaLocation="  
      7.        http://www./schema/beans http://www./schema/beans/spring-beans.xsd  
      8.        http://www./schema/context http://www./schema/context/spring-context.xsd  
      9.        http://www./schema/mvc http://www./schema/mvc/spring-mvc.xsd  
      10.        ">  
      11.     <!-- 通過web.xml中的 org.springframework.web.servlet.DispatcherServlet 加載的  -->  
      12.     <!-- 請參考 http://jinnianshilongnian./blog/1602617  -->  
      13.     <context:component-scan base-package="com.sishuok.mvc" use-default-filters="false">  
      14.         <context:include-filter type="annotation" ="org.springframework.stereotype.Controller"/>  
      15.     </context:component-scan>  
      16.     <mvc:annotation-driven/>  
      17.     <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
      18.         <property name="prefix" value="/WEB-INF/jsp/"/>  
      19.         <property name="suffix" value=".jsp"/>  
      20.     </bean>  
      21. </beans>  

       

      web.xml配置:此處就不貼了,請前往github查看。

       

      對于context:component-scan注意事項請參考《context:component-scan掃描使用上的容易忽略的use-default-filters》和《第三章 DispatcherServlet詳解 ——跟開濤學(xué)SpringMVC》。

       

      等價的注解風格配置: 

      AppConfig.java:等價于spring-config.xml

      Java代碼  收藏代碼
      1. package com.sishuok.config;  
      2.   
      3. import org.springframework.context.annotation.ComponentScan;  
      4. import org.springframework.context.annotation.Configuration;  
      5. import org.springframework.context.annotation.FilterType;  
      6. import org.springframework.stereotype.Controller;  
      7.   
      8. @Configuration  
      9. @ComponentScan(basePackages = "com.sishuok.mvc", excludeFilters = {  
      10.         @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})  
      11. })  
      12. public class AppConfig {  
      13. }  

       

      MvcConfig.java:等價于spring-mvc.xml

      Java代碼  收藏代碼
      1. package com.sishuok.config;  
      2.   
      3. import org.springframework.context.annotation.Bean;  
      4. import org.springframework.context.annotation.ComponentScan;  
      5. import org.springframework.context.annotation.Configuration;  
      6. import org.springframework.context.annotation.FilterType;  
      7. import org.springframework.stereotype.Controller;  
      8. import org.springframework.web.servlet.ViewResolver;  
      9. import org.springframework.web.servlet.config.annotation.EnableWebMvc;  
      10. import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;  
      11. import org.springframework.web.servlet.view.InternalResourceViewResolver;  
      12.   
      13. @Configuration  
      14. @EnableWebMvc  
      15. @ComponentScan(basePackages = "com.sishuok.mvc", useDefaultFilters = false, includeFilters = {  
      16.         @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})  
      17. })  
      18. public class MvcConfig extends WebMvcConfigurationSupport {  
      19.   
      20.     @Bean  
      21.     public ViewResolver viewResolver() {  
      22.         InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();  
      23.         viewResolver.setPrefix("/WEB-INF/jsp/");  
      24.         viewResolver.setSuffix(".jsp");  
      25.         return viewResolver;  
      26.     }  
      27.   
      28. }  

      WebInitializer.java:注冊相應(yīng)的web.xml中的組件

      Java代碼  收藏代碼
      1. package com.sishuok.config;  
      2.   
      3. import org.springframework.web.WebApplicationInitializer;  
      4. import org.springframework.web.context.ContextLoaderListener;  
      5. import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;  
      6. import org.springframework.web.filter.CharacterEncodingFilter;  
      7. import org.springframework.web.servlet.DispatcherServlet;  
      8.   
      9. import javax.servlet.DispatcherType;  
      10. import javax.servlet.FilterRegistration;  
      11. import javax.servlet.ServletException;  
      12. import javax.servlet.ServletRegistration;  
      13. import java.util.EnumSet;  
      14.   
      15. public class WebInitializer implements WebApplicationInitializer {  
      16.   
      17.     @Override  
      18.     public void onStartup(javax.servlet.ServletContext sc) throws ServletException {  
      19.   
      20.         AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();  
      21.         rootContext.register(AppConfig.class);  
      22.         sc.addListener(new ContextLoaderListener(rootContext));  
      23.   
      24.         //2、springmvc上下文  
      25.         AnnotationConfigWebApplicationContext springMvcContext = new AnnotationConfigWebApplicationContext();  
      26.         springMvcContext.register(MvcConfig.class);  
      27.         //3、DispatcherServlet  
      28.         DispatcherServlet dispatcherServlet = new DispatcherServlet(springMvcContext);  
      29.         ServletRegistration.Dynamic dynamic = sc.addServlet("dispatcherServlet", dispatcherServlet);  
      30.         dynamic.setLoadOnStartup(1);  
      31.         dynamic.addMapping("/");  
      32.   
      33.         //4、CharacterEncodingFilter  
      34.         CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();  
      35.         characterEncodingFilter.setEncoding("utf-8");  
      36.         FilterRegistration filterRegistration =  
      37.                 sc.addFilter("characterEncodingFilter", characterEncodingFilter);  
      38.         filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false"/");  
      39.   
      40.     }  
      41. }  

      對于WebInitializer,請參考《Spring4新特性——Groovy Bean定義DSL

      到此基本的配置就搞定了,接下來看看如何測試吧。 

       

      1.1 以前的測試方式

      Java代碼  收藏代碼
      1. package com.sishuok.mvc.controller;  
      2. //省略import  
      3. public class UserControllerTest {  
      4.   
      5.     private UserController userController;  
      6.   
      7.     @Before  
      8.     public void setUp() {  
      9.         userController = new UserController();  
      10.         //安裝userCtroller依賴 比如userService  
      11.     }  
      12.   
      13.     @Test  
      14.     public void testView() {  
      15.         MockHttpServletRequest req = new MockHttpServletRequest();  
      16.         ModelAndView mv = userController.view(1L, req);  
      17.   
      18.         ModelAndViewAssert.assertViewName(mv, "user/view");  
      19.         ModelAndViewAssert.assertModelAttributeAvailable(mv, "user");  
      20.   
      21.     }  
      22. }  

      準備控制器:我們通過new方式創(chuàng)建一個,然后手工查找依賴注入進去(比如從spring容器獲取/new的);

      Mock Request:此處使用Spring提供的Mock API模擬一個HttpServletRequest,其他的Servlet API也提供了相應(yīng)的Mock類,具體請查看Javadoc;

      訪問控制器方法:通過直接調(diào)用控制器方法進行訪問,此處無法驗證Spring MVC框架的類型轉(zhuǎn)換、數(shù)據(jù)驗證等是否正常;

      ModelAndViewAssert:通過這個Assert API驗證我們的返回值是否正常;

       

      對于單元測試步驟請參考:加速Java應(yīng)用開發(fā)速度3——單元/集成測試+CI 

       

      這種方式的缺點已經(jīng)說過了,如不能走Spring MVC完整流程(不能走Servlet的過濾器鏈、SpringMVC的類型轉(zhuǎn)換、數(shù)據(jù)驗證、數(shù)據(jù)綁定、攔截器等等),如果做基本的測試沒問題,這種方式就是純粹的單元測試,我們想要的功能其實是一種集成測試,不過后續(xù)部分不區(qū)分。

       

      1.2 安裝測試環(huán)境

      spring mvc測試框架提供了兩種方式,獨立安裝和集成Web環(huán)境測試(此種方式并不會集成真正的web環(huán)境,而是通過相應(yīng)的Mock API進行模擬測試,無須啟動服務(wù)器)。

       

      獨立測試方式

      Java代碼  收藏代碼
      1. public class UserControllerStandaloneSetupTest {  
      2.     private MockMvc mockMvc;  
      3.     @Before  
      4.     public void setUp() {  
      5.         UserController userController = new UserController();  
      6.         mockMvc = MockMvcBuilders.standaloneSetup(userController).build();  
      7.     }  
      8. }  

      1、首先自己創(chuàng)建相應(yīng)的控制器,注入相應(yīng)的依賴

      2、通過MockMvcBuilders.standaloneSetup模擬一個Mvc測試環(huán)境,通過build得到一個MockMvc

      3、MockMvc:是我們以后測試時經(jīng)常使用的API,后邊介紹

       

      集成Web環(huán)境方式

      Java代碼  收藏代碼
      1. //XML風格  
      2. @RunWith(SpringJUnit4ClassRunner.class)  
      3. @WebAppConfiguration(value = "src/main/webapp")  
      4. @ContextHierarchy({  
      5.         @ContextConfiguration(name = "parent", locations = "classpath:spring-config.xml"),  
      6.         @ContextConfiguration(name = "child", locations = "classpath:spring-mvc.xml")  
      7. })  
      8.   
      9. //注解風格  
      10. //@RunWith(SpringJUnit4ClassRunner.class)  
      11. //@WebAppConfiguration(value = "src/main/webapp")  
      12. //@ContextHierarchy({  
      13. //        @ContextConfiguration(name = "parent", classes = AppConfig.class),  
      14. //        @ContextConfiguration(name = "child", classes = MvcConfig.class)  
      15. //})  
      16. public class UserControllerWebAppContextSetupTest {  
      17.   
      18.     @Autowired  
      19.     private WebApplicationContext wac;  
      20.     private MockMvc mockMvc;  
      21.   
      22.     @Before  
      23.     public void setUp() {  
      24.         mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();  
      25.     }  
      26. }  

      1、@WebAppConfiguration:測試環(huán)境使用,用來表示測試環(huán)境使用的ApplicationContext將是WebApplicationContext類型的;value指定web應(yīng)用的根;

      2、@ContextHierarchy:指定容器層次,即spring-config.xml是父容器,而spring-mvc.xml是子容器,請參考《第三章 DispatcherServlet詳解 ——跟開濤學(xué)SpringMVC

      3、通過@Autowired WebApplicationContext wac:注入web環(huán)境的ApplicationContext容器;

      4、然后通過MockMvcBuilders.webAppContextSetup(wac).build()創(chuàng)建一個MockMvc進行測試;

       

      到此測試環(huán)境就搭建完成了,根據(jù)需要選擇使用哪種方式即可。相關(guān)配置請前往github查看。

       

      1.3、HelloWorld

      Java代碼  收藏代碼
      1. @Test  
      2. public void testView() throws Exception {  
      3.     MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/user/1"))  
      4.             .andExpect(MockMvcResultMatchers.view().name("user/view"))  
      5.             .andExpect(MockMvcResultMatchers.model().attributeExists("user"))  
      6.             .andDo(MockMvcResultHandlers.print())  
      7.             .andReturn();  
      8.       
      9.     Assert.assertNotNull(result.getModelAndView().getModel().get("user"));  
      10. }  

      1、mockMvc.perform執(zhí)行一個請求;

      2、MockMvcRequestBuilders.get("/user/1")構(gòu)造一個請求

      3、ResultActions.andExpect添加執(zhí)行完成后的斷言

      4、ResultActions.andDo添加一個結(jié)果處理器,表示要對結(jié)果做點什么事情,比如此處使用MockMvcResultHandlers.print()輸出整個響應(yīng)結(jié)果信息。

      5、ResultActions.andReturn表示執(zhí)行完成后返回相應(yīng)的結(jié)果。

       

      整個測試過程非常有規(guī)律:

      1、準備測試環(huán)境

      2、通過MockMvc執(zhí)行請求

      3.1、添加驗證斷言

      3.2、添加結(jié)果處理器

      3.3、得到MvcResult進行自定義斷言/進行下一步的異步請求

      4、卸載測試環(huán)境

       

      對于單元測試步驟請參考:加速Java應(yīng)用開發(fā)速度3——單元/集成測試+CI

       

      1.4、了解測試API

      Spring mvc測試框架提供了測試MVC需要的API,主要包括Servlet/JSP Mock、MockMvcBuilder、MockMvc、RequestBuilder、ResultMatcher、ResultHandler、MvcResult等。另外提供了幾個靜態(tài)工廠方法便于測試:MockMvcBuilders、MockMvcRequestBuilders、MockMvcResultMatchers、MockMvcResultHandlers。在使用時請使用靜態(tài)方法導(dǎo)入方便測試,如:

      Java代碼  收藏代碼
      1. import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;  
      2. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;  
      3. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;  
      4. import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;  

       

      Servlet/JSP API Mock 

      提供了對Servlet 3 相應(yīng)API的Mock,如:

      MockServletContext

      MockHttpServletRequest

      MockHttpServletResponse

      ……

      具體請查看spring-test模塊的org.springframework.mock.web包。

       

       

      MockMvcBuilder/MockMvcBuilders

      MockMvcBuilder是用來構(gòu)造MockMvc的構(gòu)造器,其主要有兩個實現(xiàn):StandaloneMockMvcBuilder和DefaultMockMvcBuilder,分別對應(yīng)之前的兩種測試方式。對于我們來說直接使用靜態(tài)工廠MockMvcBuilders創(chuàng)建即可:

      MockMvcBuilders.webAppContextSetup(WebApplicationContext context):指定WebApplicationContext,將會從該上下文獲取相應(yīng)的控制器并得到相應(yīng)的MockMvc;

      MockMvcBuilders.standaloneSetup(Object... controllers):通過參數(shù)指定一組控制器,這樣就不需要從上下文獲取了;

       

      其中DefaultMockMvcBuilder還提供了如下API:

      addFilters(Filter... filters)/addFilter(Filter filter, String... urlPatterns):添加javax.servlet.Filter過濾器

      defaultRequest(RequestBuilder requestBuilder):默認的RequestBuilder,每次執(zhí)行時會合并到自定義的RequestBuilder中,即提供公共請求數(shù)據(jù)的;

      alwaysExpect(ResultMatcher resultMatcher):定義全局的結(jié)果驗證器,即每次執(zhí)行請求時都進行驗證的規(guī)則;

      alwaysDo(ResultHandler resultHandler):定義全局結(jié)果處理器,即每次請求時都進行結(jié)果處理;

      dispatchOptions:DispatcherServlet是否分發(fā)OPTIONS請求方法到控制器;

       

      StandaloneMockMvcBuilder繼承了DefaultMockMvcBuilder,又提供了如下API:

      setMessageConverters(HttpMessageConverter<?>...messageConverters):設(shè)置HTTP消息轉(zhuǎn)換器;

      setValidator(Validator validator):設(shè)置驗證器;

      setConversionService(FormattingConversionService conversionService):設(shè)置轉(zhuǎn)換服務(wù);

      addInterceptors(HandlerInterceptor... interceptors)/addMappedInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors):添加spring mvc攔截器;

      setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager):設(shè)置內(nèi)容協(xié)商管理器;

      setAsyncRequestTimeout(long timeout):設(shè)置異步超時時間;

      setCustomArgumentResolvers(HandlerMethodArgumentResolver... argumentResolvers):設(shè)置自定義控制器方法參數(shù)解析器;

      setCustomReturnValueHandlers(HandlerMethodReturnValueHandler... handlers):設(shè)置自定義控制器方法返回值處理器;

      setHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers)/setHandlerExceptionResolvers(HandlerExceptionResolver... exceptionResolvers):設(shè)置異常解析器;

      setViewResolvers(ViewResolver...resolvers):設(shè)置視圖解析器;

      setSingleView(View view):設(shè)置單個視圖,即視圖解析時總是解析到這一個(僅適用于只有一個視圖的情況);

      setLocaleResolver(LocaleResolver localeResolver):設(shè)置Local解析器;

      setFlashMapManager(FlashMapManager flashMapManager):設(shè)置FlashMapManager,如存儲重定向數(shù)據(jù);

      setUseSuffixPatternMatch(boolean useSuffixPatternMatch):設(shè)置是否是后綴模式匹配,如“/user”是否匹配"/user.*",默認真即匹配;

      setUseTrailingSlashPatternMatch(boolean useTrailingSlashPatternMatch):設(shè)置是否自動后綴路徑模式匹配,如“/user”是否匹配“/user/”,默認真即匹配;

      addPlaceHolderValue(String name, String value) :添加request mapping中的占位符替代;

       

      因為StandaloneMockMvcBuilder不會加載Spring MVC配置文件,因此就不會注冊我們需要的一些組件,因此就提供了如上API用于注冊我們需要的相應(yīng)組件。

       

      MockMvc

      使用之前的MockMvcBuilder.build()得到構(gòu)建好的MockMvc;這個是mvc測試的核心API,對于該API的使用方式如下:

      Java代碼  收藏代碼
      1. MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/user/1"))  
      2.        .andExpect(MockMvcResultMatchers.view().name("user/view"))  
      3.        .andExpect(MockMvcResultMatchers.model().attributeExists("user"))  
      4.        .andDo(MockMvcResultHandlers.print())  
      5.        .andReturn();  

      perform:執(zhí)行一個RequestBuilder請求,會自動執(zhí)行SpringMVC的流程并映射到相應(yīng)的控制器執(zhí)行處理;

      andExpect:添加ResultMatcher驗證規(guī)則,驗證控制器執(zhí)行完成后結(jié)果是否正確;

      andDo:添加ResultHandler結(jié)果處理器,比如調(diào)試時打印結(jié)果到控制臺;

      andReturn:最后返回相應(yīng)的MvcResult;然后進行自定義驗證/進行下一步的異步處理;

       

      另外還提供了以下API:

      setDefaultRequest:設(shè)置默認的RequestBuilder,用于在每次perform執(zhí)行相應(yīng)的RequestBuilder時自動把該默認的RequestBuilder合并到perform的RequestBuilder中;

      setGlobalResultMatchers:設(shè)置全局的預(yù)期結(jié)果驗證規(guī)則,如我們通過MockMvc測試多個控制器時,假設(shè)它們都想驗證某個規(guī)則時,就可以使用這個;

      setGlobalResultHandlers:設(shè)置全局的ResultHandler結(jié)果處理器;

        

      RequestBuilder/MockMvcRequestBuilders

      從名字可以看出,RequestBuilder用來構(gòu)建請求的,其提供了一個方法buildRequest(ServletContext servletContext)用于構(gòu)建MockHttpServletRequest;其主要有兩個子類MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(如文件上傳使用),即用來Mock客戶端請求需要的所有數(shù)據(jù)。

       

      MockMvcRequestBuilders主要API:

      MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根據(jù)uri模板和uri變量值得到一個GET請求方式的MockHttpServletRequestBuilder;如get("/user/{id}", 1L);

      MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables):同get類似,但是是POST方法;

      MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables):同get類似,但是是PUT方法;

      MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) :同get類似,但是是DELETE方法;

      MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables):同get類似,但是是OPTIONS方法;

      MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables):提供自己的Http請求方法及uri模板和uri變量,如上API都是委托給這個API;

      MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables):提供文件上傳方式的請求,得到MockMultipartHttpServletRequestBuilder;

      RequestBuilder asyncDispatch(final MvcResult mvcResult):創(chuàng)建一個從啟動異步處理的請求的MvcResult進行異步分派的RequestBuilder;

       

      接下來再看看MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder API:

      MockHttpServletRequestBuilder API:

      MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders):添加頭信息;

      MockHttpServletRequestBuilder contentType(MediaType mediaType):指定請求的contentType頭信息;

      MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes):指定請求的Accept頭信息;

      MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content):指定請求Body體內(nèi)容;

      MockHttpServletRequestBuilder cookie(Cookie... cookies):指定請求的Cookie;

      MockHttpServletRequestBuilder locale(Locale locale):指定請求的Locale;

      MockHttpServletRequestBuilder characterEncoding(String encoding):指定請求字符編碼;

      MockHttpServletRequestBuilder requestAttr(String name, Object value) :設(shè)置請求屬性數(shù)據(jù);

      MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<String, Object> sessionAttributes):設(shè)置請求session屬性數(shù)據(jù);

      MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map<String, Object> flashAttributes):指定請求的flash信息,比如重定向后的屬性信息;

      MockHttpServletRequestBuilder session(MockHttpSession session) :指定請求的Session;

      MockHttpServletRequestBuilder principal(Principal principal) :指定請求的Principal;

      MockHttpServletRequestBuilder contextPath(String contextPath) :指定請求的上下文路徑,必須以“/”開頭,且不能以“/”結(jié)尾;

      MockHttpServletRequestBuilder pathInfo(String pathInfo) :請求的路徑信息,必須以“/”開頭;

      MockHttpServletRequestBuilder secure(boolean secure):請求是否使用安全通道;

      MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor):請求的后處理器,用于自定義一些請求處理的擴展點;

       

      MockMultipartHttpServletRequestBuilder繼承自MockHttpServletRequestBuilder,又提供了如下API:

      MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上傳的文件;

       

      ResultActions

      調(diào)用MockMvc.perform(RequestBuilder requestBuilder)后將得到ResultActions,通過ResultActions完成如下三件事:

      ResultActions andExpect(ResultMatcher matcher) :添加驗證斷言來判斷執(zhí)行請求后的結(jié)果是否是預(yù)期的;

      ResultActions andDo(ResultHandler handler) :添加結(jié)果處理器,用于對驗證成功后執(zhí)行的動作,如輸出下請求/結(jié)果信息用于調(diào)試;

      MvcResult andReturn() :返回驗證成功后的MvcResult;用于自定義驗證/下一步的異步處理;

       

      ResultMatcher/MockMvcResultMatchers

      ResultMatcher用來匹配執(zhí)行完請求后的結(jié)果驗證,其就一個match(MvcResult result)斷言方法,如果匹配失敗將拋出相應(yīng)的異常;spring mvc測試框架提供了很多***ResultMatchers來滿足測試需求。注意這些***ResultMatchers并不是ResultMatcher的子類,而是返回ResultMatcher實例的。Spring mvc測試框架為了測試方便提供了MockMvcResultMatchers靜態(tài)工廠方法方便操作;具體的API如下:

      HandlerResultMatchers handler():請求的Handler驗證器,比如驗證處理器類型/方法名;此處的Handler其實就是處理請求的控制器;

      RequestResultMatchers request():得到RequestResultMatchers驗證器;

      ModelResultMatchers model():得到模型驗證器;

      ViewResultMatchers view():得到視圖驗證器;

      FlashAttributeResultMatchers flash():得到Flash屬性驗證;

      StatusResultMatchers status():得到響應(yīng)狀態(tài)驗證器;

      HeaderResultMatchers header():得到響應(yīng)Header驗證器;

      CookieResultMatchers cookie():得到響應(yīng)Cookie驗證器;

      ContentResultMatchers content():得到響應(yīng)內(nèi)容驗證器;

      JsonPathResultMatchers jsonPath(String , Object ... args)/ResultMatcher jsonPath(String , Matcher<T> matcher):得到Json表達式驗證器;

      XpathResultMatchers xpath(String , Object... args)/XpathResultMatchers xpath(String , Map<String, String> namespaces, Object... args):得到Xpath表達式驗證器;

      ResultMatcher forwardedUrl(final String expectedUrl):驗證處理完請求后轉(zhuǎn)發(fā)的url(絕對匹配);

      ResultMatcher forwardedUrlPattern(final String urlPattern):驗證處理完請求后轉(zhuǎn)發(fā)的url(Ant風格模式匹配,@since spring4);

      ResultMatcher redirectedUrl(final String expectedUrl):驗證處理完請求后重定向的url(絕對匹配);

      ResultMatcher redirectedUrlPattern(final String expectedUrl):驗證處理完請求后重定向的url(Ant風格模式匹配,@since spring4);

       

      得到相應(yīng)的***ResultMatchers后,接著再調(diào)用其相應(yīng)的API得到ResultMatcher,如ModelResultMatchers.attributeExists(final String... names)判斷Model屬性是否存在。具體請查看相應(yīng)的API。再次就不一一列舉了。

       

       

      ResultHandler/MockMvcResultHandlers

      ResultHandler用于對處理的結(jié)果進行相應(yīng)處理的,比如輸出整個請求/響應(yīng)等信息方便調(diào)試,Spring mvc測試框架提供了MockMvcResultHandlers靜態(tài)工廠方法,該工廠提供了ResultHandler print()返回一個輸出MvcResult詳細信息到控制臺的ResultHandler實現(xiàn)。

       

       

      MvcResult

      即執(zhí)行完控制器后得到的整個結(jié)果,并不僅僅是返回值,其包含了測試時需要的所有信息,如:

      MockHttpServletRequest getRequest():得到執(zhí)行的請求;

      MockHttpServletResponse getResponse():得到執(zhí)行后的響應(yīng);

      Object getHandler():得到執(zhí)行的處理器,一般就是控制器;

      HandlerInterceptor[] getInterceptors():得到對處理器進行攔截的攔截器;

      ModelAndView getModelAndView():得到執(zhí)行后的ModelAndView;

      Exception getResolvedException():得到HandlerExceptionResolver解析后的異常;

      FlashMap getFlashMap():得到FlashMap;

      Object getAsyncResult()/Object getAsyncResult(long timeout):得到異步執(zhí)行的結(jié)果;

       

      1.5 測試示例

      測試普通控制器 

      Java代碼  收藏代碼
      1. //測試普通控制器  
      2. mockMvc.perform(get("/user/{id}"1)) //執(zhí)行請求  
      3.         .andExpect(model().attributeExists("user")) //驗證存儲模型數(shù)據(jù)  
      4.         .andExpect(view().name("user/view")) //驗證viewName  
      5.         .andExpect(forwardedUrl("/WEB-INF/jsp/user/view.jsp"))//驗證視圖渲染時forward到的jsp  
      6.         .andExpect(status().isOk())//驗證狀態(tài)碼  
      7.         .andDo(print()); //輸出MvcResult到控制臺  

       

      測試普通控制器,但是URL錯誤,即404

      Java代碼  收藏代碼
      1. //找不到控制器,404測試  
      2. MvcResult result = mockMvc.perform(get("/user2/{id}"1)) //執(zhí)行請求  
      3.         .andDo(print())  
      4.         .andExpect(status().isNotFound()) //驗證控制器不存在  
      5.         .andReturn();  
      6. Assert.assertNull(result.getModelAndView()); //自定義斷言  

       

      得到MvcResult自定義驗證    

      Java代碼  收藏代碼
      1. MvcResult result = mockMvc.perform(get("/user/{id}"1))//執(zhí)行請求  
      2.         .andReturn(); //返回MvcResult  
      3. Assert.assertNotNull(result.getModelAndView().getModel().get("user")); //自定義斷言  

       

      驗證請求參數(shù)綁定到模型數(shù)據(jù)及Flash屬性 

      Java代碼  收藏代碼
      1. mockMvc.perform(post("/user").param("name""zhang")) //執(zhí)行傳遞參數(shù)的POST請求(也可以post("/user?name=zhang"))  
      2.         .andExpect(handler().handlerType(UserController.class)) //驗證執(zhí)行的控制器類型  
      3.         .andExpect(handler().methodName("create")) //驗證執(zhí)行的控制器方法名  
      4.         .andExpect(model().hasNoErrors()) //驗證頁面沒有錯誤  
      5.         .andExpect(flash().attributeExists("success")) //驗證存在flash屬性  
      6.         .andExpect(view().name("redirect:/user")); //驗證視圖  

       

      驗證請求參數(shù)驗證失敗出錯  

      Java代碼  收藏代碼
      1. mockMvc.perform(post("/user").param("name""admin")) //執(zhí)行請求  
      2.         .andExpect(model().hasErrors()) //驗證模型有錯誤  
      3.         .andExpect(model().attributeDoesNotExist("name")) //驗證存在錯誤的屬性  
      4.         .andExpect(view().name("showCreateForm")); //驗證視圖  

       

      文件上傳 

      Java代碼  收藏代碼
      1. //文件上傳  
      2. byte[] bytes = new byte[] {12};  
      3. mockMvc.perform(fileUpload("/user/{id}/icon", 1L).file("icon", bytes)) //執(zhí)行文件上傳  
      4.         .andExpect(model().attribute("icon", bytes)) //驗證屬性相等性  
      5.         .andExpect(view().name("success")); //驗證視圖  

       

      JSON請求/響應(yīng)驗證

      測試時需要安裝jackson Json和JsonPath依賴: 

      Java代碼  收藏代碼
      1. <dependency>  
      2.     <groupId>com.fasterxml.jackson.core</groupId>  
      3.     <artifactId>jackson-databind</artifactId>  
      4.     <version>${jackson2.version}</version>  
      5. </dependency>  
      6.   
      7. <dependency>  
      8.     <groupId>com.jayway.jsonpath</groupId>  
      9.     <artifactId>json-path</artifactId>  
      10.     <version>${jsonpath.version}</version>  
      11.     <scope>test</scope>  
      12. </dependency>  
      版本:<jsonpath.version>0.9.0</jsonpath.version>、<jackson2.version>2.2.3</jackson2.version> 
      Java代碼  收藏代碼
      1. String requestBody = "{\"id\":1, \"name\":\"zhang\"}";  
      2. mockMvc.perform(post("/user")  
      3.             .contentType(MediaType.APPLICATION_JSON).content(requestBody)  
      4.             .accept(MediaType.APPLICATION_JSON)) //執(zhí)行請求  
      5.         .andExpect(content().contentType(MediaType.APPLICATION_JSON)) //驗證響應(yīng)contentType  
      6.         .andExpect(jsonPath("$.id").value(1)); //使用Json path驗證JSON 請參考http:///articles/JsonPath/  
      7.   
      8. String errorBody = "{id:1, name:zhang}";  
      9. MvcResult result = mockMvc.perform(post("/user")  
      10.         .contentType(MediaType.APPLICATION_JSON).content(errorBody)  
      11.         .accept(MediaType.APPLICATION_JSON)) //執(zhí)行請求  
      12.         .andExpect(status().isBadRequest()) //400錯誤請求  
      13.         .andReturn();  
      14.   
      15. Assert.assertTrue(HttpMessageNotReadableException.class.isAssignableFrom(result.getResolvedException().getClass()));//錯誤的請求內(nèi)容體  

       

      XML請求/響應(yīng)驗證

      測試時需要安裝spring oxm和xstream依賴: 

      Java代碼  收藏代碼
      1. <dependency>  
      2.     <groupId>com.thoughtworks.xstream</groupId>  
      3.     <artifactId>xstream</artifactId>  
      4.     <version>${xsream.version}</version>  
      5.     <scope>test</scope>  
      6. </dependency>  
      7.   
      8. <dependency>  
      9.     <groupId>org.springframework</groupId>  
      10.     <artifactId>spring-oxm</artifactId>  
      11.     <version>${spring.version}</version>  
      12.     <scope>test</scope>  
      13. </dependency>  
      版本:<xstream.version>1.4.4</xstream.version>
      Java代碼  收藏代碼
      1. //XML請求/響應(yīng)  
      2. String requestBody = "<user><id>1</id><name>zhang</name></user>";  
      3. mockMvc.perform(post("/user")  
      4.         .contentType(MediaType.APPLICATION_XML).content(requestBody)  
      5.         .accept(MediaType.APPLICATION_XML)) //執(zhí)行請求  
      6.         .andDo(print())  
      7.         .andExpect(content().contentType(MediaType.APPLICATION_XML)) //驗證響應(yīng)contentType  
      8.         .andExpect(xpath("/user/id/text()").string("1")); //使用XPath表達式驗證XML 請參考http://www.w3school.com.cn/xpath/  
      9.   
      10. String errorBody = "<user><id>1</id><name>zhang</name>";  
      11. MvcResult result = mockMvc.perform(post("/user")  
      12.         .contentType(MediaType.APPLICATION_XML).content(errorBody)  
      13.         .accept(MediaType.APPLICATION_XML)) //執(zhí)行請求  
      14.         .andExpect(status().isBadRequest()) //400錯誤請求  
      15.         .andReturn();  
      16.   
      17. Assert.assertTrue(HttpMessageNotReadableException.class.isAssignableFrom(result.getResolvedException().getClass()));//錯誤的請求內(nèi)容體  

       

      異常處理  

      Java代碼  收藏代碼
      1. //異常處理  
      2. MvcResult result = mockMvc.perform(get("/user/exception")) //執(zhí)行請求  
      3.         .andExpect(status().isInternalServerError()) //驗證服務(wù)器內(nèi)部錯誤  
      4.         .andReturn();  
      5.   
      6. Assert.assertTrue(IllegalArgumentException.class.isAssignableFrom(result.getResolvedException().getClass()));  

       

      靜態(tài)資源 

      Java代碼  收藏代碼
      1. //靜態(tài)資源  
      2. mockMvc.perform(get("/static/app.js")) //執(zhí)行請求  
      3.         .andExpect(status().isOk()) //驗證狀態(tài)碼200  
      4.         .andExpect(content().string(CoreMatchers.containsString("var")));//驗證渲染后的視圖內(nèi)容包含var  
      5.   
      6. mockMvc.perform(get("/static/app1.js")) //執(zhí)行請求  
      7.         .andExpect(status().isNotFound());  //驗證狀態(tài)碼404  

      異步測試 

      Java代碼  收藏代碼
      1. //Callable  
      2. MvcResult result = mockMvc.perform(get("/user/async1?id=1&name=zhang")) //執(zhí)行請求  
      3.         .andExpect(request().asyncStarted())  
      4.         .andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class))) //默認會等10秒超時  
      5.         .andReturn();  
      6.   
      7. mockMvc.perform(asyncDispatch(result))  
      8.         .andExpect(status().isOk())  
      9.         .andExpect(content().contentType(MediaType.APPLICATION_JSON))  
      10.         .andExpect(jsonPath("$.id").value(1));  
      Java代碼  收藏代碼
      1. //DeferredResult  
      2. result = mockMvc.perform(get("/user/async2?id=1&name=zhang")) //執(zhí)行請求  
      3.         .andExpect(request().asyncStarted())  
      4.         .andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class)))  //默認會等10秒超時  
      5.         .andReturn();  
      6.   
      7. mockMvc.perform(asyncDispatch(result))  
      8.         .andExpect(status().isOk())  
      9.         .andExpect(content().contentType(MediaType.APPLICATION_JSON))  
      10.         .andExpect(jsonPath("$.id").value(1));  

      此處請在第一次請求時加上 andExpect(request().asyncResult(CoreMatchers.instanceOf(User.class)))這樣會等待結(jié)果返回/超時,無須自己設(shè)置線程等待了;此處注意request().asyncResult一定是在第一次請求發(fā)出;然后第二次通過asyncDispatch進行異步請求。

       

      添加自定義過濾器

      Java代碼  收藏代碼
      1. mockMvc = webAppContextSetup(wac).addFilter(new MyFilter(), "/*").build();  
      2. mockMvc.perform(get("/user/1"))  
      3.         .andExpect(request().attribute("filter"true));  

       

      全局配置 

      Java代碼  收藏代碼
      1. mockMvc = webAppContextSetup(wac)  
      2.         .defaultRequest(get("/user/1").requestAttr("default"true)) //默認請求 如果其是Mergeable類型的,會自動合并的哦mockMvc.perform中的RequestBuilder  
      3.         .alwaysDo(print())  //默認每次執(zhí)行請求后都做的動作  
      4.         .alwaysExpect(request().attribute("default"true)) //默認每次執(zhí)行后進行驗證的斷言  
      5.         .build();  
      6.   
      7. mockMvc.perform(get("/user/1"))  
      8.         .andExpect(model().attributeExists("user"));  

       

      以上代碼請參考我的github。更多參考示例請前往Spring github。

       

       

      只要記住測試步驟,按照步驟操作,整個測試過程是非常容易理解的:

      1、準備測試環(huán)境

      2、通過MockMvc執(zhí)行請求

      3.1、添加驗證斷言

      3.2、添加結(jié)果處理器

      3.3、得到MvcResult進行自定義斷言/進行下一步的異步請求

      4、卸載測試環(huán)境

       

      對于單元測試步驟請參考:加速Java應(yīng)用開發(fā)速度3——單元/集成測試+CI

       

      下一篇介紹RestTemplate客戶端測試。

       

       

      歡迎加入spring群134755960進行交流。

       

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多