SSH框架下单元测试的实现

实现的功能

  • 实现了部门的增删改查
  • 对Action进行了单元测试
  • 对Service 进行了单元测试,通过mock的方式实现。

实现的步骤

一、对Action层的单元测试实现

1、首先在pom文件中需要引入的依赖


<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>2.1.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>

说明:

在此处我们引入struts2-junit-plugin.2.1.8.jar,因为其里面有测试Struts2中action的类

StrutsSpringTestCase,用来测试ssh中的action。

2、新建一个测试类

如果你使用的是idea,那么你可以直接在需要建立测试类的Action类中

按ctrl+shift+t,新建一个测试类。如DepartmentActionTest

3、如果是普通的action的话,

待测试代码:

       public String findById() {
String did = ServletActionContext.getRequest().getParameter("did");
department=departmentService.findByDid(Integer.valueOf(did));
return "goEditDepartment";
}

测试代码:

       @Test
public void testFindById() throws Exception {
/*这个函数相当@Before注解的函数,是调用单元测试后的时候,
首先会执行的方法。可以在这里面做一些必要的准备工作*/
request.setParameter("did", "1");
ActionProxy proxy = getActionProxy("/department_findById.action");
DepartmentAction action = (DepartmentAction) proxy.getAction();
String result = action.findById();
Assert.assertEquals("goEditDepartment", result);
}

4、如果是返回json的action的话,待测试代码:

 public void  findAll() {
List<Department> departmentList= departmentService.findAll();
JSONObject jsonObject = new JSONObject();
if (CollectionUtils.isEmpty(departmentList)) {
jsonObject.put("key", "success");
jsonObject.put("data", JSON.toJSONString(departmentList));
writeJson(jsonObject);
return;
}
jsonObject.put("key", "success");
jsonObject.put("data", JSON.toJSONString(departmentList));
writeJson(jsonObject);
}

测试代码:

String result = executeAction("/json_findAll.action");
Assert.assertNotNull(result);
JSONObject jsonObject = JSON.parseObject(result);
if ("success".equals(jsonObject.getString("key"))) {
List<Department> departmentList = JSON.parseArray(jsonObject.getString("data"), Department.class);
if (CollectionUtils.isEmpty(departmentList)) {
return;
}
for (Department department : departmentList) {
System.out.println(department.toString());
}
}

5、关于lazy问题的解决:首先在setUp()函数中加入下述代码:

     @Override
protected void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = lookupSessionFactory(request);
Session hibernateSession= getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory,
new SessionHolder(hibernateSession));
//在只读模式下(FlushMode.NEVER/MANUAL)写操作不被允许
hibernateSession.setFlushMode(FlushMode.AUTO);
}

然后在添加两个私有函数

 private Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
Session session = sessionFactory.openSession();
FlushMode flushMode = FlushMode.NEVER;
if (flushMode != null) {
session.setFlushMode(flushMode);
}
return session;
}
private SessionFactory lookupSessionFactory(HttpServletRequest request) {
//“sessionFactory”是你spring配置文件(通常是application.xml)中的SessionFactory。
//如:org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean
return (SessionFactory)this.applicationContext.getBean("sessionFactory");
}

说明:通过lookupSessionFactory()方法获取这个测试环境中的org.hibernate.SessionFactory实体对象,其中

applicationContext是org.springframework.context.ApplicationContext的实现org.springframework.context.support.GenericApplicationContext

我们可以通过它的getBean方法来获取你配置文件中配置的SessionFactory。使用注解是org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean

不需要使用注解的时候可以使用org.springframework.orm.hibernate.LocalSessionFactoryBean来实现。

该单元测试需要加载spring配置文件信息,默认加载路径是你项目的src目录下,文件名默认为applicationContext.xml,如果路径不对或者

文件名不同,则需要重写getContextLocations()方法,如

 protected String getContextLocations() {
return "classpath*:applicationContext.xml";
}

关于实现web session的问题,很简单,该类提供了一个MockHttpServletRequest成员变量,我们只要mock一个session出来,然后加入到这个request中,就可以实现session的模拟了。示例代码如下:

  HttpSession  session = new MockHttpSession();
String sessionId = UUID.randomUUID().toString();
session.setAttribute(ConstParameter.USER_SESSION, sessionId);
//user是一个用户信息的类,你可以根据你的需要自己定义
UserInfor user = new UserInfo();
user.setUserId(1);
user.setName("xxx");
session.setAttribute(ConstParameter.USER_INFO, user);
request.setSession(session);

关于action的单元测试我们就说完了。

二、Service的单元测试

接下来我们在说说关于service的测试,

同样,我们先从依赖说起,需要添加的依赖:

    <powermock.version>1.7.1</powermock.version>

   <!--********************powermock使用*********************-->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>

此处我们采用的是powermock+junit 进行mock测试。为啥使用powermock呢,毋庸置疑,由于他的功能比较强大

1、首先,我们我们看看待测试的代码:

 @Override
public List<MyInvoice> getMyInvoice(String buyerId) {
if (StringUtils.isBlank(buyerId)) {
return null;
}
List<MyInvoice> myInvoices = new ArrayList<MyInvoice>();
String url = baseDataUrl + UrlConfig.GET_MYINVOICE_URL + "?t=" + VerifyBaseUtil.getT()
+ "&token=" + VerifyBaseUtil.getToken() + "&buyerId=" + buyerId;
System.out.println("MyInvoiceServiceImpl getMyInvoice接口请求参数为:" + url);
try {
String responseInfo = HttpUtil.getHttp(url);
System.out.println("MyInvoiceServiceImpl getMyInvoice接口返回结果为:" + responseInfo);
Map<String, Object> result = JSON.parseObject(responseInfo, Map.class);
if (DistrictReturnNum.SUCCESS.getValue().equals(result.get("code"))) {
myInvoices = JSON.parseArray(JSON.toJSONString(result.get("result")), MyInvoice.class);
return myInvoices;
}
} catch (Exception e) {
System.out.println("MyInvoiceServiceImpl getMyInvoice 程序出错,查询发票失败"+e.getMessage());
return null;
}
return null;
}

getMyInvoice方法是一个调用外部接口的方法,通过http协议进行通信。这儿有两个问题

1.HttpUtil.getHttp(url) 是一个静态方法,我们如何mock?

2.我们如何mock这个方法所在的实现类?因为该实现类是通过spring ioc 容器生成并注入的。

要回答这两个问题,我们首先需要看看,我们的测试代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest(HttpUtil.class)
public class MyInvoiceServiceImplTest {
@InjectMocks
private MyInvoiceService myInvoiceService = new MyInvoiceServiceImpl();
@Before
public void setUp(){
PowerMockito.mockStatic(HttpUtil.class);
}
@Test
public void testGetMyInvoice() throws Exception {
String result_http="{\"result\":[{\"addDate\":1509010776000,\"buyerId\":" +
"\"9E59A2D27B7748848FB65041B854240E\",\"headName\":\"项伟测试\"," +
"\"headType\":\"0\",\"invoiceId\":\"9747A51B57FF4EA781F1CFDF73A0D9DF\"," +
"\"invoiceType\":\"0\",\"isDefault\":0},{\"addDate\":1509092635000,\"" +
"buyerId\":\"9E59A2D27B7748848FB65041B854240E\",\"editDate\":1509094177000,\"headName\":\"项伟测试二\",\"headType\":\"0\",\"invoiceId\":\"720CF6C50E594283B01C79D03D6D52B2\"" +
",\"invoiceType\":\"0\",\"isDefault\":1}],\"msg\":\"成功\",\"code\":104}";
// 1、 buyerId为空
String buyerId = null;
Assert.assertEquals(null, myInvoiceService.getMyInvoice(buyerId));
// 2、buyerId不为空
buyerId = "FF8080810F5E601526";
PowerMockito.when(HttpUtil.getHttp(anyString())).thenReturn(result_http);
List<MyInvoice> result = myInvoiceService.getMyInvoice(buyerId);
Assert.assertEquals(2,result.size());
}
}

第一个问题:我们通过PowerMockito.mockStatic(HttpUtil.class); 一个静态方法的实现类。然后就可以调用该静态方法。

第二个问题:@InjectMocks注解来mock我们需要测试的业务类。

至此,我们就可以通过powermock对service层的方法进行单元测试了。

运行环境

  • 环境描述:Struts2+Spring4.2.4+hibernate4

    JAVA 1.7
  • 额外依赖第三方jar包,请参考pom.xml

SSH框架下单元测试的实现的更多相关文章

  1. java ssh 框架下 利用junit4 spring-test进行单元测试

    ssh框架下  由于bean实列 都交给spring 管理,要做单元测试就比较苦难,junit4 引入注解方便很多: 1. 加入依赖包 使用Spring的测试框架需要加入以下依赖包: JUnit 4 ...

  2. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

  3. SSH框架下的表单重复提交

    前几天做了一个功能,是在某个操作后,刷新父页面的,刷新时弹出了下面图的框: 网上查了之后发现这个框是表单重复提交时出现的.分析后发现,这个页面的上一个动作是form submit(在ssh框架下),这 ...

  4. SSH框架下的多表增删改查

    下载地址:SSH框架下的多表增删改查 点击进入码云Git下载 点击进入CSDN下载 项目结构: 项目代码就不全部贴出来了,只贴下核心代码.需要项目的自己可以去下载. package com.atgui ...

  5. Java之基于Eclipse搭建SSH框架(下)

    在上篇博客里,我简介了Tomcat滴配置与Struts2滴搭建,假设对这个还不会滴童鞋去看一下我滴上篇博客<Java之基于Eclipse搭建SSH框架(上)>.今天我们接着上篇博客滴内容. ...

  6. SSH框架下ajax调用action并生成JSON再传递到客户端【以get和post方式提交】

    需要完成的任务: 主要是把JSP页面上图片ID传给服务器端,服务器读取cookie看是否有username,如果有则根据ID读取MongoDB数据库,读出图片URL,再存放到mysql中的collec ...

  7. layerweb弹层组件(SSH框架下)

    action类 这里主要看业务方法中表单路径中的(isClose = "1";return resUri;) public class MaterialsAction extend ...

  8. 基于SSH框架下登录验证码模块的实现

    1.前端页面代码: 主要以jQuery的ajax异步请求实现. ... <script type="text/javascript" src="${pageCont ...

  9. SSH框架下页面跳转入门篇

    一.完成目标,因为WEB-INF下面的界面不能通过输入地址的方式直接访问,所以需要在后台定义一个方法跳转过去. 步骤1:.创建普通类继承ActionSupport类,并定义一个方法返回需要跳转的路径 ...

随机推荐

  1. Android系统升级那些事儿【转】

    本文转载自:http://blog.csdn.net/chenyufei1013/article/details/12705719 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?) ...

  2. Java 8 实战 P2 Functional-style data processing

    目录 Chapter 4. Introducing streams Chapter 5. Working with streams Chapter 6. Collecting data with st ...

  3. PCB 周期计算采用 SQL 函数调用.net Dll 标量函数 实现

    PCB 周期计算采用 SQL函数调用.net Dll实现 (实现代码重用目的) 玩过SQL SERVER数据库经常经需要写存储过程,函数之类的,当业务逻辑过于复杂,用SQL去写简直是恶梦, 这里以PC ...

  4. 正确的缩写document。querySelector

    北京的夕阳,伴随淡淡的霾殇.从写字楼望去,光线是那么昏黄.没有孤雁,也没有霞光,遥想当年,还是 jQuery 独霸一方.那时的我们,写程序都习惯了使用 $,至少在对美元符号的喜爱上,与 PHP 达成了 ...

  5. [Apple开发者帐户帮助]一、开始(3)账户信息

    您帐户中显示的部分取决于您是否拥有免费帐户或是否已注册付费程序(Apple Developer Program或Apple Developer Enterprise Program).此外,您可以在这 ...

  6. # 深入理解Redis(二)——内存管理的建议与技巧

    引语 随着使用Redis的深入,我们不可避免的需要深入了解优化Redis的内存,本章将重点讲解Redis的内存优化之道,同时推荐大家阅读memory-optimization一文. 想要高效的使用Re ...

  7. ListView(2)最简单的上拉刷新、下拉刷新代码

    效果 最简单的上拉刷新和下拉刷新,当listview滚动到底部时向上拉刷新数据.当listview滚动到最顶部时下拉刷新.       图1,上拉刷新 图2,下拉刷新 1.设置lisview 加载he ...

  8. SQLServer2008 表连接时null 和 null 无法匹配?

    例如 select * from tbl_a a left join tbl_b b on b.docno=a.docno and b.project=a.project where a.docno= ...

  9. P1375 嵌套矩形

    题目Problem 嵌套矩形 Time Limit: 1000ms    Memory Limit: 131072KB 描述Descript. 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形 ...

  10. 安装rails卡住很慢 出现302 Moved Temporarily

    在MAC上安装rails的时候,使用命令$ gem install rails 发现一直没响应,使用$ gem install rails-V命令发现,安装会在中间卡住,出现302 Moved Tem ...