spring mvc test analysis

(前端时间为spring mvc 写测试 后面没来得及和同事分享)

spring 提供了 mvc测试框架 detail : http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/new-in-3.2.html#new-in-3.2-spring-mvc-test 下面是一个小例子:


import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.server.setup.MockMvcBuilders.standaloneSetup;

import org.springframework.test.web.server.MockMvc;
import org.junit.Before;
import org.junit.Test;

public class ApplicationInfoControllerTest {

	private MockMvc mockMvc;

	@Before
	public void setup() {
		this.mockMvc = standaloneSetup(new ApplicationInfoController()).build();
	}

	@Test
	public void testContentType() throws Exception {
		this.mockMvc.perform(get("/applicationInfo/list")).andExpect(redirectedUrl("/admin/applicationInfo/customer_form_list.ftl"));
	}
	
	
}


MockMvc 详细调用过程如下:

spring mvc test ROOT

---->MockMvc#perform
-------->创建RequestBuilder
-------->调用buildRequest(ServletContext servletContext) 构建请求Uri,method等 --> 生成MockHttpServletRequest .同时创建一个新的MockHttpServletResponse
-------->创建DefaultMvcResult对象  用于后面判断测试结果
-------->调用MockFilterChain.doFilter()方法
----------------->从MockFilterChain取出filter(TestDispatcherServlet对象) 继续调用doFilter
----------------------->ServletFilterProxy 调用doFilter方法
----------------------------->代理Servlet(TestDispatcherServlet对象) 调用 service(request, response)方法
-------------------------------------->调用父类FrameworkServlet 方法 service(HttpServletRequest request, HttpServletResponse response) 提供处理http PATCH请求支持 (父类HttpServlet 没有PATCH处理)
--------------------------------------------->继续调用父类HttpServlet  方法 service(HttpServletRequest request, HttpServletResponse response)
-------------------------------------->调用父类FrameworkServlet 方法 doGet  ---> processRequest(request, response)
--------------------------------->调用父类DispatcherServlet 方法 doService  保存请求参数  数据丢失
--------------------------------->调用父类DispatcherServlet 方法 doDispatch
-------------------------------------->1. 检查 multipart/form-data
-------------------------------------->2. 获取handlerMappings  
-------------------------------------->3. 根据URL path 从handlerMap 获取hander(HandlerExecutionChain对象:保存匹配的拦截器列表 interceptorList和实际的bean对象)
-------------------------------------->4. 组装HandlerAdapter  
-------------------------------------->5. 调用applyPreHandle方法  处理拦截器列表(preHandle方法) HandlerAdapter
-------------------------------------->6. 实际匹配的bean(Controller)调用 :HandlerAdapter#handle方法 :子类RequestMappingHandlerAdapter方法 handleInternal
-------------------------------------------------->调用invokeHandleMethod-->继续调用ServletInvocableHandlerMethod#invokeAndHandle 
------------------------------------------------------------------>InvocableHandlerMethod#invokeForRequest
--------------------------------------------------------------------------->invoke(args)
---------------------------------------------------------------------------------->getBridgedMethod().invoke(getBean(){controller}, args{controller方法参数}) 反射
-------------------------------------->7. 返回ModelAndView 然后进行applyPostHandle处理 最后processDispatchResult 渲染视图render(mv, request, response);
----------------------------->代理Servlet(TestDispatcherServlet对象) 重写 render(mv, request, response)方法:设置返回结果 mvcResult.setModelAndView(mv)
-------->最后返回ResultActions实现类 将结果mvcResult用于测试判断


---->测试结果verify  上面返回ResultActions实现类 andExpect 方法
-------------->ResultMatcher#match(mvcResult)
------------------------>assertEquals("Redirected URL", expectedUrl, result.getResponse().getRedirectedUrl());