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

大的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;

}

}

}

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

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-01 03:00:34

Java Web并发单元测试摘记(1)的相关文章

Java Web 并发单元测试(2)

使用GroboUtils进行简单并发单元测试,实现测试和监控和单个线程执行的控制,这里展示简单案例的测试过程: 1.建立要测试的线程TestRunnable1 /** * */ package com.dtsz.groboTest; import net.sourceforge.groboutils.junit.v1.TestRunnable; /** * @author xiaoli * */ public class TestRunnable1 extends TestRunnable {

Java Web并发单元测试(1)

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

服务器-这些因素如何影响一个java web网站的并发数

问题描述 这些因素如何影响一个java web网站的并发数 服务器tomcat:最大连接数(maxThreads)和(acceptCount) 缓存redis:最大连接数(maxActive).最大空闲连接数(maxIdle) 数据源c3p0:最大连接数(maxPoolSize) 请教大牛解释这些参数和整个web网站并发数的关系

Java Web技术经验总结(二)

该系列的第一篇在此:Java Web技术经验总结一,主要包含我在日常工作中的经验和心得体会(如有不足之处欢迎指出). Maven的使用经验 依赖的scope有test.provided.compile等.test:一般是单元测试场景使用,在编译环境加入classpath,但打包时不会加入,如junit等:provided:表示容器或者JDK已经提供该依赖,打包时不需要打包入war:compile:默认范围,在工程环境的classpath(编译环境)和打包(如果是WAR包,会包含在WAR包中)时候

java web实现增删改查后,应该学习哪些高级技术?

问题描述 java web实现增删改查后,应该学习哪些高级技术? 做了个小项目,实现了curd,想继续往缓存,并发,负载高级深入,请推荐一个详细的高级技术路线?最好有书 解决方案 javaweb深入浅出,不过这个方向研究,主要还是在公司里学的会更实用些 解决方案二: 多线程,Socket,I/O JSP.EL.JSTL,AJAX JavaScript,jQuery JSON,XML EJB(可忽略) 各种框架 ......太多了 解决方案三: 多线程,Socket,I/O JSP.EL.JSTL

jsp 网站开发-JAVA WEB应用,一个操作只能同时有一个用户操作

问题描述 JAVA WEB应用,一个操作只能同时有一个用户操作 一个B/S系统,其中有个调用Linux脚本的操作,执行时间较长,要求系统只能同时有一个用户执行此操作,否则提示其他用户正在执行,请问下该如何实现呢? 解决方案 在該腳本開頭添加"ps -ef | grep 'yourshell'",返回監測結果,看是繼續執行,或是退出交回到java 解决方案二: 这个可以当启动linux脚本时写一个标识位到一个文件内.当其它用户再启动linux脚本时检测这个文件.是否存在即可. 解决方案三

Java Web中的入侵检测及简单实现

web 在Java Web应用程中,特别是网站开发中,我们有时候需要为应用程序增加一个入侵检测程序来防止恶意刷新的功能,防止非法用户不断的往Web应用中重复发送数据.当然,入侵检测可以用很多方法实现,包括软件.硬件防火墙,入侵检测的策略也很多.在这里我们主要介绍的是Java Web应用程序中通过软件的方式实现简单的入侵检测及防御. 该方法的实现原理很简单,就是用户访问Web系统时记录每个用户的信息,然后进行对照,并根据设定的策略(比如:1秒钟刷新页面10次)判断用户是否属于恶意刷新. 我们的入侵

Java Web Framework综述

web Java Web Framework综述0.简介本文介绍Java Web Framework的基本工作原理,和一些常用的开源Web MVC Framework(Struts, Web Work, Tapestry, Echo, JSF, Maverick, Spring MVC, Turbine, Cocoon, Barracuda). Web开发的最重要的基本功是HTTP:Java Web开发的最重要的基本功是Servlet Specification.HTTP和Servlet Spe

Java Web前端的高性能

引言 在前端优化的第一部分中,主要讲解了对静态资源的一些优化措施,包括图片压缩.CSS Sprites 技术. GZIP 压缩等.这一部分,本文将讲解前端优化里重要的 Flush 机制.动静分离.HTTP 持久连接.HTTP 协议灵活应用. CDN 等.结合这些技术或思想,相信会使 Java Web 应用程序的性能更上一层楼. Flush 机制的使用 实际上 在 Web 技术中,Flush 机制并不新鲜,它的思想是无需等到网页内容全部加载完毕,一次性写回客户端,而是可以部分逐 次的返回.如果网页