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/

相关文章
|
15天前
|
Java 测试技术
SpringBoot整合单元测试&&关于SpringBoot单元测试找不到Mapper和Service报java.lang.NullPointerException的错误
SpringBoot整合单元测试&&关于SpringBoot单元测试找不到Mapper和Service报java.lang.NullPointerException的错误
17 0
|
15天前
|
XML 前端开发 Java
《手把手教你》系列技巧篇(十四)-java+ selenium自动化测试-元素定位大法之By xpath上卷(详细教程)
【4月更文挑战第6天】按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍定位倒数二个方法:By xpath。xpath 的定位方法, 非常强大。使用这种方法几乎可以定位到页面上的任意元素。xpath 是XML Path的简称, 由于HTML文档本身就是一个标准的XML页面,所以我们可以使用Xpath 的用法来定位页面元素。XPath 是XML 和Path的缩写,主要用于xml文档中选择文档中节点。基于XML树状文档结构,XPath语言可以用在整棵树中寻找指定的节点。
43 0
|
1天前
|
XML Web App开发 测试技术
python的Web自动化测试
【4月更文挑战第16天】Python在Web自动化测试中广泛应用,借助Selenium(支持多浏览器交互)、BeautifulSoup(解析HTML/XML)、Requests(发送HTTP请求)和Unittest(测试框架)等工具。测试步骤包括环境搭建、编写测试用例、初始化浏览器、访问页面、操作元素、验证结果、关闭浏览器及运行报告。注意浏览器兼容性、动态内容处理和错误处理。这些组合能提升测试效率和质量。
11 6
|
Java 测试技术
Java 中的单元测试和集成测试策略
【4月更文挑战第19天】本文探讨了Java开发中的单元测试和集成测试。单元测试专注于单一类或方法的功能验证,使用测试框架如JUnit,强调独立性、高覆盖率和及时更新测试用例。集成测试则验证模块间交互,通过逐步集成或模拟对象来检测系统整体功能。两者相辅相成,确保软件质量和降低修复成本。
|
4天前
|
前端开发 JavaScript Java
《手把手教你》系列技巧篇(二十五)-java+ selenium自动化测试-FluentWait(详细教程)
【4月更文挑战第17天】其实今天介绍也讲解的也是一种等待的方法,有些童鞋或者小伙伴们会问宏哥,这也是一种等待方法,为什么不在上一篇文章中竹筒倒豆子一股脑的全部说完,反而又在这里单独写了一篇。那是因为这个比较重要,所以宏哥专门为她量身定制了一篇。FluentWait是Selenium中功能强大的一种等待方式,翻译成中文是流畅等待的意思。在介绍FluentWait之前,我们来讨论下为什么需要设置等待,我们前面介绍了隐式等待和显式等待。
27 3
|
4天前
|
安全 Java
深入理解 Java 多线程和并发工具类
【4月更文挑战第19天】本文探讨了Java多线程和并发工具类在实现高性能应用程序中的关键作用。通过继承`Thread`或实现`Runnable`创建线程,利用`Executors`管理线程池,以及使用`Semaphore`、`CountDownLatch`和`CyclicBarrier`进行线程同步。保证线程安全、实现线程协作和性能调优(如设置线程池大小、避免不必要同步)是重要环节。理解并恰当运用这些工具能提升程序效率和可靠性。
|
6天前
|
Java 测试技术 定位技术
《手把手教你》系列技巧篇(二十三)-java+ selenium自动化测试-webdriver处理浏览器多窗口切换下卷(详细教程)
【4月更文挑战第15天】本文介绍了如何使用Selenium进行浏览器窗口切换以操作不同页面元素。首先,获取浏览器窗口句柄有两种方法:获取所有窗口句柄的集合和获取当前窗口句柄。然后,通过`switchTo().window()`方法切换到目标窗口句柄。在项目实战部分,给出了一个示例,展示了在百度首页、新闻页面和地图页面之间切换并输入文字的操作。最后,文章还探讨了在某些情况下可能出现的问题,并提供了一个简单的本地HTML页面示例来演示窗口切换的正确操作。
27 0
|
6天前
|
Java 开发者
Java中多线程并发控制的实现与优化
【4月更文挑战第17天】 在现代软件开发中,多线程编程已成为提升应用性能和响应能力的关键手段。特别是在Java语言中,由于其平台无关性和强大的运行时环境,多线程技术的应用尤为广泛。本文将深入探讨Java多线程的并发控制机制,包括基本的同步方法、死锁问题以及高级并发工具如java.util.concurrent包的使用。通过分析多线程环境下的竞态条件、资源争夺和线程协调问题,我们提出了一系列实现和优化策略,旨在帮助开发者构建更加健壮、高效的多线程应用。
6 0
|
7天前
|
存储 缓存 安全
Java并发基础之互斥同步、非阻塞同步、指令重排与volatile
在Java中,多线程编程常常涉及到共享数据的访问,这时候就需要考虑线程安全问题。Java提供了多种机制来实现线程安全,其中包括互斥同步(Mutex Synchronization)、非阻塞同步(Non-blocking Synchronization)、以及volatile关键字等。 互斥同步(Mutex Synchronization) 互斥同步是一种基本的同步手段,它要求在任何时刻,只有一个线程可以执行某个方法或某个代码块,其他线程必须等待。Java中的synchronized关键字就是实现互斥同步的常用手段。当一个线程进入一个synchronized方法或代码块时,它需要先获得锁,如果
22 0
|
8天前
|
Web App开发 Java 应用服务中间件
【Java Web】在 IDEA 中部署 Tomcat
【Java Web】在 IDEA 中部署 Tomcat
20 0