Java Web并发单元测试摘记(1)

原创 2013年12月03日 14:02:44

     大的web项目开发和运行环境都在服务器容器中进行为主,包括调试过程,也都是单例进过Web触发进行测试。在Web项目中设计使用Spring、hibernate、JBPM工作流、ehcache各种框架或组件。这些东西在一起配置好一个有效的、覆盖所有环境的单元测试用例也比较复杂。所有配置好一个可用有效的单元测试环境十分必要。并且面对单元测试对并发要求的不支持,还得加入必要的并发测试组件,满足测试全面系统白盒测试要求。

这里总结几种有效的配置单元测试方式:

      1、直接使用Junit4组件,进行简单单元测试,在setUp()中初始化各种测试环境如下:

@Override
	protected void setUp() throws Exception {
		super.setUp();
		String[] paths = { "classpath:applicationContext.xml" };
		ApplicationContext ctx = new ClassPathXmlApplicationContext(paths);
		SpringContextListener.setApplicationContext(ctx);
		// ############模拟servlet容器启动,手动更改配置文件路径
		Constant.CURRENT_PROJECT_PATH = "src/";
		// ############直接容器中获取bean
		userManager = (UserManager) ctx.getBean("userManager");
		userService = (UserService) ctx.getBean("userService");
	}

2、使用Sprint-test.jar框架,支持事务可注解方式启动的单元测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@TransactionConfiguration(transactionManager="transactionManager",defaultRollback=false) //true将会回滚所有操作,默认没有该注解为回滚
public class JBPMProcessTest2 extends  AbstractTransactionalJUnit4SpringContextTests{

以上都只能暂时支持简单功能的单元测试。但是要测试并发和压力等。需要加入一个常用的框架,支持在单元测试中注入多线程和并发。

具体参见:http://blog.csdn.net/zhangyaoming2004/article/details/7619489 下面附有Jar包下载 http://yunpan.cn/QUtVay66VnU4T

我们具体使用的功能不是很多,这些并发测试可以嵌入到上面两种单元测试方式中:如下:

/**
 * 
 */
package com.dtsz.model.service.test;

import net.sourceforge.groboutils.junit.v1.TestRunnable;

import com.dtsz.model.entity.report.common.InvokeSource;
import com.dtsz.model.service.ExcelReportLogicService;
import com.dtsz.model.service.TaskLogicService;
import com.dtsz.model.util.ExcelReportUtil;
import com.dtsz.view.vo.authenticator.UserVO;
import com.dtsz.view.vo.webservice.ExcelReportResult;

/**
 * 模拟插件端数据上报的并发操作测试
 * 
 * @author xiaoli
 * 
 */
public class CreateMulltiTaskReportGroboThread extends TestRunnable {

	TaskLogicService taskLogicService;
	ExcelReportLogicService excelReportLogicService;
	
	private String reportMap;
	private UserVO user;
	private InvokeSource invokeSource;
	private String bbq;
	
	public CreateMulltiTaskReportGroboThread(String reportMap, UserVO user, InvokeSource invokeSource,String bbq) {
		super();
		this.reportMap = reportMap;
		this.user = user;
		this.invokeSource = invokeSource;
		this.bbq = bbq;
		init();
	}
	
	public void init() {
		taskLogicService = (TaskLogicService)ExcelReportUtil.getBean("taskLogicService");
		excelReportLogicService = (ExcelReportLogicService)ExcelReportUtil.getBean("excelReportLogicService");
		
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.sourceforge.groboutils.junit.v1.TestRunnable#runTest()
	 */
	@Override
	public void runTest() throws Throwable {
		// TODO Auto-generated method stub
		// ########################模拟当前任务该报表期任务上报
		//保存数据
		ExcelReportResult result = taskLogicService.reportData(reportMap, user, invokeSource);
		excelReportLogicService.saveData(result);
		System.out.println("报表期为:"+this.bbq+"已上报"); 
	}

}

单元测试并发:

/**
 * 
 */
package com.dtsz.model.service.test;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;
import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;
import net.sourceforge.groboutils.junit.v1.TestRunnable;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.dtsz.model.entity.authenticator.User;
import com.dtsz.model.entity.report.common.InvokeSource;
import com.dtsz.model.service.authenticator.UserManager;
import com.dtsz.model.service.authenticator.UserService;
import com.dtsz.model.service.exception.BaseAppException;
import com.dtsz.model.util.BeanUtil2;
import com.dtsz.model.util.Constant;
import com.dtsz.model.util.Encryption;
import com.dtsz.view.util.SpringContextListener;
import com.dtsz.view.vo.authenticator.UserVO;

/**
 * 模拟数据上报,这里的初始化数据根据插件端传入数据组合来的,当前只有根据报表期生成初始化数据
 * 
 * @author xiaoli
 * 
 */
public class CreateMultiTaskReportTest3 extends TestCase {


	private UserManager userManager;

	private UserService userService;

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		String[] paths = { "classpath:applicationContext.xml" };
		ApplicationContext ctx = new ClassPathXmlApplicationContext(paths);
		SpringContextListener.setApplicationContext(ctx);
		// ############模拟servlet容器启动,手动更改配置文件路径
		Constant.CURRENT_PROJECT_PATH = "src/";
		// ############直接容器中获取bean
		userManager = (UserManager) ctx.getBean("userManager");
		userService = (UserService) ctx.getBean("userService");
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
	}

	@Test
	public void test(){

		// ###########自动生成报表期串集合
		List<String> bbqs = new ArrayList<String>();
		UnitTestUtils.imitateCreateMultiBbq(bbqs, 2, "2048", "5");

		// 创建线程
		TestRunnable[] tr = new TestRunnable[bbqs.size()];
		int processCount = 0;

		// ##########对这些数据进行填报
		for (String bbq : bbqs) {
			// 模拟上报数据
			String reportMap = "{taskID:\"402880ee425a92f501425aa75ad50002\",bbq_:\""
					+ bbq
					+ "\""
					+ ",bbhid:\"402855b942099b1b014209b1177e03f5\",approvalFlag:2,reportFlag:False,auditFlag:False,sheetMap:"
					+ "[{id:\"402880ee425a92f501425aa75ad60004\",sheetType:\"BASIC\",values:{}}]}";
			// 模拟上报的user
			UserVO user = null;
			try {
				user = checkUser("xl1", "1");
			} catch (BaseAppException e) {
				e.printStackTrace();
			} // 模拟插件端checkUser
			String sessionInfo = "{institutionname:\"南昌分行\",institutioncode:\"A01NC\",username:\"肖力1"
					+ "1\",usercode:\"xl1\",rolecode:\"null\",bbhId:\"402855b942099b1b014209b1177e03f5\",bbhcode:\"B01b\",btype:\"BASIC\",taskid:\"402880ee425a92f501425a"
					+ "a75ad50002\",bbhname:\"基层财务b\",bbq:\"" + bbq
					+ "\",frequency:\"MONTH\",SESSIONDIMENSION:{}}";
			try {
				userService.updateSession(sessionInfo, user);
			} catch (BaseAppException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			} // 模拟插件端updateSession
			// 初始化上报方式
			InvokeSource invokeSource = InvokeSource.WSCALL;

			CreateMulltiTaskReportGroboThread reportThread = new CreateMulltiTaskReportGroboThread(reportMap,user, invokeSource,bbq);
			tr[processCount] = reportThread;
			processCount++;
		}
		System.out.println("#######################################计时开始########################"); 
		long startTime = System.currentTimeMillis();
		// 生成测试线程运行器
		MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(tr);
		// 运行测试线程
		try {
			mttr.runTestRunnables();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		System.out.println("#######################一共耗时:"
				+ String.valueOf((System.currentTimeMillis() - startTime) / 1000) + "秒");
	}

	/**
	 * xl1 1
	 * */
	public UserVO checkUser(String userid,
			String password) throws BaseAppException {
		Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put("UserName", userid);
		paramMap.put("Password", password);
		List<User> users = userManager.findByCodeCache(userid);
		List<User> needUsers = new ArrayList<User>();
		if (users != null && users.size() > 0) {
			for (User user : users) {
				if (user.getState() && user.getCode().equals(userid)
						&& user.getPassword().equals(Encryption.encryption(password))) {
					needUsers.add(user);
				}
			}
		}
		// 通过验证
		if (needUsers != null && needUsers.size() > 0) {
			User user = needUsers.get(0);
			// 获取用户权限,并存放于session中
			// UserVO userVO = userManager.getUserPermission(user.getId());
			String ipAddress = "0.0.0.0";
			UserVO userVO = new UserVO();
			BeanUtil2.copyProperties(user, userVO);
			userVO.setIpAddress(ipAddress);
			return userVO; // 通过验证
		} else {
			return null;
		}

	}

}

真实环境并发和压力测试不仅仅是在多个线程同时启动在测,还可能是增量式压力测试。这些还是要封装好和处理好。


还在进行中……

相关文章推荐

WEB通用测试用例

易用性 1、便于使用、理解、并能减少用户发生错误选择的可能性 2、当数据字段过多时,使用便于用户迅速吸取信息的方式表现信息,突出重点信息,标红等方式 3、显示与当前操作相关的信息,给...

Java Web 并发单元测试(2)

使用GroboUtils进行简单并发单元测试,实现测试和监控和单个线程执行的控制,这里展示简单案例的测试过程: 1、建立要测试的线程TestRunnable1 /** * */ package ...

selenium+java 的Web测试

之前写过一个appium的app测试 今天做了一个基于selenium2 的Web测试,打算写一下,记录一下。 测试对象:京东商城登录页面 测试功能: 1.点击“忘记密码”,是否跳转到...

Spring Web 单元测试实用HelloWorld(附代码)

Spring Web 单元测试
  • Del_Zhu
  • Del_Zhu
  • 2015年11月27日 19:45
  • 2775

使用JUnit对Web项目进行测试(二) -- 不启动服务器调试Web项目

~ ~小伙伴们在做Javaweb项目的时候,一个功能块敲完,然后提心吊胆的打开Tomcat,测试功能的时候发现总有那么一两个功能点炸成串?而且有时候是很简单的SQL语句编写错误,或者实体名字写错这种”...
  • JacXuan
  • JacXuan
  • 2017年03月21日 19:43
  • 10033

Web项目开发中 Spring整合Junit单元测试

做Web开发,发现通过Spring进行对象管理之后,做测试变得复杂了。 因为所有的Bean都需要在applicationContext.xml中加载好,之后再通过@Resource去取得。 ...
  • Ninexl
  • Ninexl
  • 2015年04月11日 12:37
  • 3744

JUnit4多线程执行测试用例

前言: 在testerhome社区中,有人评论说直接使用TestNG,就可以实现多线程,是的,但是方式不一样;我们是按照自己的需求对JUnit4自定义多线程Runner,直接在某个类加上相应的注解即...
  • neven7
  • neven7
  • 2015年05月07日 09:36
  • 9501

JAVA 模拟瞬间高并发

前些日子接到了一个面试电话,面试内容我印象很深,如何模拟一个并发?当时我的回答虽然也可以算是正确的,但自己感觉缺乏实际可以操作的细节,只有一个大概的描述。       当时我的回答是:“线程全部在同一...

java CountDownLatch 模拟多并发线程简单例子

CountDownLatch作用  CountDownLatch,是一个倒计数的锁存器,当计数减至0时触发特定的事件。 构造方法参数指定了计数的次数 countDown方法,当前线程调用此方...

Spring web项目的单元测试

Spring web项目的单元测试 /**=========================================== * Copyright (C) 20...
  • xpsharp
  • xpsharp
  • 2013年01月17日 15:29
  • 4717
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java Web并发单元测试摘记(1)
举报原因:
原因补充:

(最多只允许输入30个字)