今天花了下午的时间研究了下如何对Controller层的代码进行单元测试.
踩了不少的坑,现在总结一下
严重注意 :
spring4开始已经不兼容Servlet2 否则会报错,很多坑都是这个引起的.
Servlet3指的是 3.0.1以后的 artifactId为 <artifactId>javax.servlet-api</artifactId> Servlet2指的是 3.0.1以前的 artifactId为 <artifactId>servlet-api</artifactId> 只是做了一个普通的例子,大家可以根据自己的需求查看api,找到解决办法.PS:看别人的博客,坑比较多
package com.kbs.service;import javax.servlet.ServletContext;import javax.servlet.http.Cookie;import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;import java.io.IOException;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import org.aspectj.apache.bcel.classfile.Utility.ResultHolder;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.MediaType;import org.springframework.mock.web.MockHttpServletRequest;import org.springframework.mock.web.MockHttpServletResponse;import org.springframework.mock.web.MockHttpSession;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import org.springframework.test.context.web.WebAppConfiguration;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.MvcResult;import org.springframework.test.web.servlet.ResultActions;import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;import org.springframework.test.web.servlet.setup.MockMvcBuilders;import org.springframework.ui.ExtendedModelMap;import org.springframework.web.context.WebApplicationContext;import com.kbs.platform.controller.WDController;/** * * @author mifans */@RunWith(SpringJUnit4ClassRunner.class)@WebAppConfiguration @ContextConfiguration(locations={"classpath:applicationContext.xml"})public class SpringMockTest { @Autowired WDController wDController; @Autowired ServletContext context; @Autowired protected WebApplicationContext wac; MockMvc mockMvc; MockHttpSession session; @Before public void setup(){ mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //这个方法接受 WebApplicationContext参数,可以对任意Controller测试 // mockMvc =MockMvcBuilders.standaloneSetup(wDController).build(); 可以对单独的Controller测试 //mockMvc =MockMvcBuilders.standaloneSetup(context).build(); 测试未成功,应该是和spring的配置有关系 session= new MockHttpSession(); //可以使用session 对于包含登录的,需要验证session中的数据 } //saas/qa?k=糖尿病怎么办 String param="糖尿病怎么办"; @Test public void test() throws Exception{ ResultActions resultActions = this.mockMvc.perform(MockMvcRequestBuilders.get("/qa") .param("k",param).session(session)).andExpect(status().isOk()) //.andExpect(content().contentType("application/json;charset=UTF-8")) .andDo(print()); //这里需要需要一定要引入spring测试框架的几个静态方法类,否则找不到print(),content()方法. //对于返回json格式的可以用.accept(MediaType.APPLICATION_JSON)处理,不了解的多研究api MvcResult mvcResult = resultActions.andReturn(); String result = mvcResult.getResponse().getContentLength()+""; Cookie[] cookies=mvcResult.getResponse().getCookies(); // for (int i = 0; i < cookies.length; i++) {// System.err.println(cookies[i].getName()+"--------"+cookies[i].getValue());// } System.out.println("=====客户端获得反馈数据:" + result); } @Test public void testLogin() throws IOException { // MockHttpServletRequest request = new MockHttpServletRequest(); //MockHttpServletResponse response = new MockHttpServletResponse(); //request.setMethod("POST"); //request.addParameter("k",param); //对于确定参数的,并且参数可以构造出来的可以这么测试.以下测试成功 wDController.wdResult(param, null, null, new ExtendedModelMap()); } }
WDCController.java
package com.kbs.platform.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import com.kbs.platform.service.WDService;import com.kbs.platform.vo.WDMsgBody;@Controller("wDController")@RequestMapping("/")public class WDController { @Autowired public WDService wDService; /** * 首页 * @return */ @RequestMapping(value="qasearch",method=RequestMethod.GET) public String wd(){ return "wd/index"; } @RequestMapping(value="qa",method=RequestMethod.GET) public String wdResult(@RequestParam("k")String key,@RequestParam(value="p",required=false)Integer startNum,@RequestParam(value="s",required=false)Integer pageSize,Model model){ startNum=startNum==null?1:startNum; pageSize=pageSize==null?WDService.PAGESIZE:pageSize; /** * 此处为赶时间,先做成jsp渲染的,后期如果使用anglarjs的话,直接修改该方法的返回值为json格式即可 */ WDMsgBody wdMsgBody=wDService.accessNLP(key, startNum, pageSize); //拆分封装数据格式 model.addAttribute("data", wdMsgBody.getData());//数据 model.addAttribute("key",wdMsgBody.getKey()); //问题 model.addAttribute("curPage",wdMsgBody.getCurPage());//当前页 model.addAttribute("pageSize",wdMsgBody.getPageSize());//页面数据条数 model.addAttribute("total",wdMsgBody.getTotal()); //数据总条数 model.addAttribute("totalPage",wdMsgBody.getTotalPage()); //总页数 return "wd/qa"; } }
贴一个静态方法 print()的打印结果 Controller返回的是视图
MockHttpServletRequest: HTTP Method = GET Request URI = /qa Parameters = {k=[糖尿病怎么办]} Headers = {}Handler: Type = com.kbs.platform.controller.WDControllerAsync: Async started = false Async result = nullResolved Exception: Type = nullModelAndView: View name = wd/qa View = null Attribute = data value = [数据结果-略去] Attribute = key value = 糖尿病怎么办 Attribute = curPage value = 1 Attribute = pageSize value = 10 Attribute = total value = 546 Attribute = totalPage value = 55FlashMap: Attributes = nullMockHttpServletResponse: Status = 200 Error message = null Headers = {} Content type = null Body = Forwarded URL = wd/qa Redirected URL = null
也可以自己实现 ResultHandler 接口,下面是我的一个例子,当时没找到print()方法怎么来的,就自己实现了一个,现在看来,并没有什么卵用 (╥╯^╰╥)
package com.kbs.service;import org.springframework.test.web.servlet.MvcResult;import org.springframework.test.web.servlet.ResultHandler;class myHandler implements ResultHandler { public myHandler() { // TODO Auto-generated constructor stub } @Override public void handle(MvcResult result) throws Exception { System.err.println(result.getRequest().getRequestURI()); System.err.println(result.getResponse().getContentAsString()); System.err.println(result.getResponse().getIncludedUrl()); System.err.println(result.getResponse().getStatus()); } }
推荐几篇讲的不错的blog
http://www.cnblogs.com/0201zcr/p/5756642.html
http://www.cnblogs.com/xiadongqing/p/6211429.html
http://www.cnblogs.com/lyy-2016/p/6122144.html
http://www.cnblogs.com/kabi/p/5182102.html
http://www.cnblogs.com/wql025/p/5022310.html
http://blog.csdn.net/qianjiangqi/article/details/51087014
感谢以上作者.