基于Spring 3.0 Controller层单元测试

   今天在对基于Spring mvc架构的项目写单元测试的时候,本来想用@RunWith的方式轻松搞定它。不曾想还不是那么so easy,   一方面是controller层没有联系起来,再者就是SpringJUnit4ClassRunner启动就报不知道什么鬼错了。索性就换成mock方式,再熟悉一下spring容器加载机制也未尝不是一件好事~  废话少说,直接上代码先!!!


测试基类

 

 


package com.andy.test;

import java.io.File;
import java.util.Arrays;
import java.util.Map;

import javacommon.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
import org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping;

/**
 * 
 * Spring MVC 3.0 Controller层测试基类
 * 提供Controller层测试stub
 * 
 * @author Andy
 * @since 2012.5.10 1:25 PM
 * @version 1.0
 *
 */
public abstract class AbstractTestCase { 
	// 应用程序根配置文件(不包含applicationContext.xml配置文件)
	private final static String[] ROOT_CONFIGLOCATION = {"classpath:/spring/*-test.xml"};
	
	// 随Servlet启动时加载配置文件。(默认为applicationContext.xml/servletName-servlet.xml)
	private final static String DEFAULT_CONFIG_LOCATION = "classpath:/spring/applicationContext.xml";
	
	// 模块功能CRUD
	protected final static String MODULE_QUERY = "query";
	protected final static String MODULE_LIST = "list";
	protected final static String MODULE_SHOW = "show";
	protected final static String MODULE_CREATE = "create";
	protected final static String MODULE_SAVE = "save";
	protected final static String MODULE_EDIT = "edit";
	protected final static String MODULE_DELETE = "delete";
	
	// Logger
	protected final static Logger logger;
	
	// 对象映射处理器(映射到controller类)
	protected HandlerMapping handlerMapping;
	
	// 方法适配处理器(映射到具体方法)
	protected HandlerAdapter handlerAdapter;
	
	// Spring容器上下文
	protected XmlWebApplicationContext webApplicationContext;
	
	static{
		// 清除旧的测试日志文件
		File logFile = null;
		logFile = new File("logs/test.log");
		if(logFile.exists()){
			logFile.setReadable(true);
			logFile.setWritable(true);
			logFile.delete();
		}
		
		// 加载测试日志配置文件
		PropertyConfigurator.configure(AbstractTestCase.class.getResource("/log4j-test.properties"));
		logger = Logger.getLogger(AbstractTestCase.class);
	}
	
	@Before
	public  void setUp(){
		// 创建web应用程序根上下文,该上下文解析并管理系统实例
		XmlWebApplicationContext rootWebApplicationContext = new XmlWebApplicationContext();
		rootWebApplicationContext.setConfigLocations(ROOT_CONFIGLOCATION);
		// 创建servletContext上下文
		MockServletContext servletContext = new MockServletContext();
		rootWebApplicationContext.setServletContext(servletContext);
		rootWebApplicationContext.refresh();
		//servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, rootWebApplicationContext);
	    
		// 创建web应用程序上下文,管理controller层请求业务
		webApplicationContext = new XmlWebApplicationContext();
		webApplicationContext.setConfigLocation(DEFAULT_CONFIG_LOCATION);
		webApplicationContext.setParent(rootWebApplicationContext);
		webApplicationContext.refresh();
		
		servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext);

		
		// 获取默认mapping,adapter
		 handlerMapping = webApplicationContext.getBean(ControllerClassNameHandlerMapping.class);
		 handlerAdapter = webApplicationContext.getBean(AnnotationMethodHandlerAdapter.class);
	}
	
	// TODO 测试流程   创建->修改->查询-> 删除
	@Test
	public void testMain(){
		// 创建
		this.testCreateUI();
		this.testSave();
		
		// 修改
		this.testEditUI();
		this.testUpdate();
		
		// 查询
		this.testQuery();
		this.testList();
		this.testShow();
		
		// 删除
		this.testDelete();
	}
	
	/**
	 * 跳转到创建UI
	 */
	protected abstract void testCreateUI();
	
	/**
	 * 创建功能
	 */
	protected abstract void testSave();
	
	/**
	 * 跳转到编辑UI
	 */
	protected abstract void testEditUI();
	
	/**
	 * 修改功能
	 */
	protected abstract void testUpdate();
	
	/**
	 * 按条件查询
	 */
	protected abstract void testQuery();
	
	/**
	 * 分页查询所有记录
	 */
	protected abstract void testList();
	
	/**
	 * 查询某条记录详情
	 */
	protected abstract void testShow();
	
	/**
	 * 删除某条记录
	 */
	protected abstract void testDelete();

	/**
	 * 执行请求
	 * @param request	http请求对象
	 * @param response  http响应对象
	 * @return			UI信息
	 */
	protected ModelAndView execute(HttpServletRequest request , HttpServletResponse response){
		try {
			HandlerExecutionChain chain = handlerMapping.getHandler(request);
			return handlerAdapter.handle(request, response, chain.getHandler());
		} catch (Exception e) {
			// TODO 忽略 no thread bind request exception。
			// 如报错,在业务方法引入HttpServletRequest即可。(eg. public void save(HttpServletRequest request){ // statement})
		}
		return null;
	}
	
	/**
	 * 封装请求信息
	 * @param uri		请求uri
	 * @param method	请求类型  默认请求类型为GET
	 *                  eg POST GET PUT DELETE HEAD TRACE OPTIONS
	 * @param params    请求参数
	 * @return          http请求对象
	 */
	protected HttpServletRequest createRequest(String uri , Map<String , String> params , RequestMethod... method ){
		if(null == uri || uri.isEmpty()){
			throw new IllegalArgumentException("It must contains request uri!");
		}
		// 构造请求
		MockHttpServletRequest request = new MockHttpServletRequest();
		request.setRequestURI(uri);
		if(null == method  || method.length == 0){
			request.setMethod(RequestMethod.GET.name());
		}else{
			request.setMethod(method[0].name());
		}
		if(null != params && !params.isEmpty()){
			request.addParameters(params);
		}
		return request;
	}
	
	@After
	public void tearDown(){
		
	}
	
	// 查询相关
	/**
	 * 查询所有数据记录
	 * 
	 * @param module	当前模块
	 * @param operate   当前操作
	 */
	protected void list(String module, String operate){
		ModelAndView view  = this.processRequest(module + operate, null);
		logger.info(StringUtils.format("【Unit Testing Info】query {0}: {1}.", module , view));
	}
	
	/**
	 * 查询某个记录详情
	 * @param module	当前模块
	 * @param operate   当前操作
	 * @param params    某记录数据参数
	 * @param method    请求类型
	 */
	protected void show(String module, String operate , Map<String,String> params , RequestMethod method){
		Assert.notEmpty(params, "The request params is null!");
		ModelAndView view = this.processRequest(module + operate, params, method);
		logger.info(StringUtils.format("【Unit Testing Info】 query {0} by params {1}: {2}.", module , params, view));
	}
	
	/**
	 * 多条件查询数据
	 * @param module	当前模块
	 * @param operate   当前操作
	 * @param params    条件数据参数
	 * @param method    请求类型
	 */
	protected void query(String module, String operate , Map<String,String> params , RequestMethod method){
		ModelAndView view = this.processRequest(module + operate, params, method);
		logger.info(StringUtils.format("【Unit Testing Info】 query {0} by params {1}: {2}.", module , params, view));
	}
	
	// 创建修改相关
	/**
	 * 请求待创建页面
	 * 
	 * @param module	当前模块
	 * @param operate   当前操作
	 */
	protected void create(String module, String operate){
		ModelAndView view = this.processRequest(module + operate, null);
		logger.info(StringUtils.format("【Unit Testing Info】 {0} create url: {1}.", module , view));
	}
	
	/**
	 * 请求待修改页面
	 * @param module	当前模块
	 * @param operate   当前操作
	 * @param params    待数据参数
	 */
	protected void edit(String module, String operate , Map<String,String> params){
		Assert.notEmpty(params, "The request params is null!");
		ModelAndView view = this.processRequest(module + operate, params);
		logger.info(StringUtils.format("【Unit Testing Info】 {0} edit url: {1}.", module , view));
	}
	
	/**
	 * 创建/修改数据请求
	 * @param module	当前模块
	 * @param operate   当前操作
	 * @param params    创建/修改数据参数
	 * @param method    请求类型
	 */
	protected void saveOrModify(String module, String operate , Map<String,String> params , RequestMethod method){
		Assert.notEmpty(params, "The request params is null!");
		this.processRequest(module + operate, params , method);
		logger.info(StringUtils.format("【Unit Testing Info】 {0} save {1} success.", module , params));
	}
	
	// 删除操作
	/**
	 * 删除数据请求
	 * @param module	当前模块
	 * @param operate   当前操作
	 * @param params    删除数据参数
	 */
	protected void delete(String module, String operate , Map<String,String[]> params){
		Assert.notEmpty(params, "The request params is null!");
		this.processRequest(module + operate, params);
		logger.info(StringUtils.format("【Unit Testing Info】 {0} delete {1} success", module , Arrays.asList(params.get("ids"))));
	}
	
	
	/**
	 * 处理用户请求
	 * 
	 * 实现构造请求数据,并发送请求,处理请求业务
	 * 
	 * @param uri		请求uri
	 * @param method	请求类型  默认请求类型为GET
	 *                  eg POST GET PUT DELETE HEAD TRACE OPTIONS
	 * @param params    请求参数
	 * @return			请求结果
	 */
	@SuppressWarnings({"rawtypes" , "unchecked"})
	protected ModelAndView processRequest(String uri , Map params , RequestMethod... method ){
		HttpServletRequest request = this.createRequest(uri, params);
		HttpServletResponse response = new MockHttpServletResponse();  
		return this.execute(request, response);
	}
}

 

单元测试用例类

 

package com.andy.test.unit;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.springframework.web.bind.annotation.RequestMethod;

import com.andy.dao.UserDao;
import com.andy.dao.RoleDao;
import com.andy.dao.RightsDao;
import com.andy.model.User;
import com.andy.model.Role;
import com.andy.model.Rights;
import com.andy.test.AbstractTestCase;

/**
 * 用户管理模块测试用例
 * 
 * @author Andy
 * @since 2012.5.10 04:45 PM
 * @version 1.0
 */
@SuppressWarnings("unchecked")
public class UserManagerTestCase extends AbstractTestCase{
	
	// 用户管理包含子模块
	private final static String USER_MODULE = "/user/";
	private final static String ROLR_MODULE = "/role/";
	private final static String RIGHTS_MODULE = "/rights/";
	
	// 测试id
	private Long userTestId;
	private Long roleTestId;
	private Long rightsTestId;
	
	@Override
	protected void testCreateUI() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void testSave() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void testEditUI() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void testUpdate() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void testQuery() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void testList() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void testShow() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void testDelete() {
		// TODO Auto-generated method stub

	}
}
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值