今天花了下午的时间研究了下如何对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.WDController
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
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 = 55
FlashMap:
Attributes = null
MockHttpServletResponse:
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
感谢以上作者.