ssh加入junit4测试

时间:2022-09-13 18:22:37

很想爆粗,就为了搞这个死人东西,花了姐姐我4个下午的时间,实在是令人发指,为了避免以后也花那么多时间去搞这个,在这里做个笔记以备以后查阅。

前提,在已经搭建出一个ssh项目的基础上增加junit4测试。

一、对action的struts和spring测试

1、导入jar包

junit-4.11、struts-junit-plugin-2.2.3(自己官方下载,这两个jar是关键,其他缺什么补什么)

2、为了项目方便,重载了StrutsSpringTestCase的一些函数,自定义了一个继承类用于公共用途

package com.scorpion.test.util;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.StrutsSpringTestCase;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
* @author ZJ
* @作用 设置ssh的公共测试环境
* @创建日期 2013-10-10下午05:18:01
* @修改人
* @修改日期
* @修改内容 TODO
* @version V1.0
*/
public class BaseTestCase extends StrutsSpringTestCase {
/**
* @Field CONTEXT_LOCATION. 设置测试的spring配置
*/
private static final String CONTEXT_LOCATION = "test.xml";/** 这个很重要 **/

@Override
protected String[] getContextLocations() {
// TODO Auto-generated method stub
return new String[] {CONTEXT_LOCATION};
}
/**
* @Description: TODO
* @param sessionFactory
* the session factory.
* @return Session
* @throws
*/
@SuppressWarnings("deprecation")
protected Session getSession(SessionFactory sessionFactory){
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
FlushMode flushMode = FlushMode.NEVER;
if(null != flushMode){
session.setFlushMode(flushMode);
}
return session;
}
/**
* @Description: TODO
* @param request
* the http request.
* @return SessionFactory
*/
protected SessionFactory lookupSessionFactory(HttpServletRequest request){
return (SessionFactory) this.applicationContext.getBean("sessionFactory");
}


/**
* @Description: 重载setUp函数,解决(hibernate+spring)jpa的lazy延迟加载问题
* @throws Exception
* java.lang.Exception.
*/
@Override
protected void setUp() throws Exception {
// TODO Auto-generated method stub
super.setUp();
SessionFactory sessionFactory = this.lookupSessionFactory(request);
Session hibernateSession = this.getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(hibernateSession));
}

}


3、接着是action test(有很多junit4的新特性和方便的地方由于整合的一些问题,没有体现出来,会在日后进行更新,让它更加完善)

package com.main.test.testcase;

import org.junit.Test;

import com.opensymphony.xwork2.ActionProxy;
import com.scorpion.test.util.BaseTestCase;

/**
* @author ZJ
* @作用 测试登录
* @创建日期 2013-9-29下午07:51:17
* @修改人
* @修改日期
* @修改内容 TODO
* @version V1.0
*/
public class LoginActionTest extends BaseTestCase{

/**
* @Field ACTION_NAME.
*/
private static final String ACTION_NAME = "userLogin.action";

/**
* @Description: 测试execute函数内的逻辑代码
*/
@Test
public void testExecuteParams() {
try {
// request paramter's data not in database
request.setParameter("uName", "12");
request.setParameter("pwd", "11");
ActionProxy proxy = this.getActionProxy(ACTION_NAME);
String result = proxy.execute();
assertEquals("error",result);

// request paramter's data is invalid.
request.setParameter("uName", "");
ActionProxy proxy1 = this.getActionProxy(ACTION_NAME);
String result1 = proxy1.execute();
assertEquals("error",result1);

// request paramter's data in database
request.setParameter("uName", "bb");
request.setParameter("pwd", "aa");
ActionProxy proxy2 = this.getActionProxy(ACTION_NAME);
String result2 = proxy2.execute();
assertEquals("success",result2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

4、为了解决jpa的延迟加载问题,需要在web.xml增加

<!-- 使用OpenSessionInViewFilter处理(hibernate+spring)jpa的延迟加载问题 -->
<filter>
<filter-name>opensession</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>

5、spring链接数据库部分是在2中有谈到的test.xml文档,其里面的内容

<?xml version="1.0" encoding="UTF-8"?>
<!-- 指定Spring配置文件的Schema信息 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<!-- 开启注解处理器 -->
<context:annotation-config/>
<!-- 扫描项目下的所有注解类 -->
<context:component-scan base-package="com.main"/>

<!-- 项目公共配置 -易受环境影响的配置环境-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- 本地服务器开发配置 -->
<value>classpath*:application.properties</value>
<!-- 生产服务器开发配置 -->
</list>
</property>
</bean>

<!-- 设置连接数据库的驱动、URL、用户名、密码 连接池最大连接数、最小连接数、初始连接数等参数 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${test.driver}"></property>
<property name="url" value="${test.url}"></property>
<property name="username" value="${test.username}"></property>
<property name="password" value="${test.password}"></property>
<!-- Connection Pooling Info -->
</bean>

<!-- 定义Hibernate的SessionFactory -->
<!-- 依赖注入数据源,注入正是上面定义的dataSource -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource">
<!-- 定义Hibernate的SessionFactory的属性 -->
<property name="hibernateProperties">
<!-- 指定数据库方言、是否自动建表 是否生成SQL语句等 -->
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
</props>
</property>

<!-- 使用了hibernate-annotations代替原有复杂mappingResources方法扫描实体类 -->
<!-- 扫描实体类的注解 -->
<property name="packagesToScan" value="com.main.entity"></property>
</bean>

<!-- 配置Hibernate的局部事务管理器,使用HibernateTransactionManager类 -->
<!-- 该类实现PlatformTransactionManager接口,是针对Hibernate的特定实现 -->
<!-- 并注入SessionFactory的引用 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />

<!-- proxy-target-class="true"表示采用动态代理类来管理事务,如果是false表示采用接口代理来管理事务(默认值为false) -->
<!--<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>-->

<!-- 配置事务增强处理Bean,指定事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 用于配置详细的事务语义 -->
<tx:attributes>
<!-- 所有以'get'开头的方法是read-only的 -->
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<!-- 其他方法使用默认的事务设置 -->
<tx:method name="*" />
</tx:attributes>
</tx:advice>

<aop:config>
<!--配置一个切入点,匹配empManager和mgrManager 两个Bean的所有方法的执行 -->
<aop:pointcut id="leePointcut" expression="execution(* com.main.service.*.*(..))" />
<!--指定在leePointcut切入点应用txAdvice事务增强处理 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="leePointcut" />
</aop:config>

</beans>

以上就是一个完整的testcase的配置和junit代码编写,为了方便管理test case,还可以写test suite

package com.main.test.testsuite;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

import com.main.test.testcase.LoginActionTest;

/**
* @author ZJ
* @作用 用户管理模块的所有test case的集合
* @创建日期 2013-9-30下午03:32:30
* @修改人
* @修改日期
* @修改内容 TODO
* @version V1.0
*/
@RunWith(Suite.class)
@SuiteClasses({LoginActionTest.class})
public class UserTestSuite {
}


二、对spring service impl的测试

1、需要的jar包:

junit-4.11、spring-test

2、编写继承AbstractTransactionalJUnit4SpringContextTests类的公共类,注意@ContextConfiguration(locations = {"classpath:test.xml"})的配置,链接数据库用的

package com.scorpion.test.util;

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;

/**
* @author ZJ
* @作用 junit4对spring的单元测试公共测试类,@ContextConfiguration读取spring的配置
* @创建日期 2013-10-11下午06:43:24
* @修改人
* @修改日期
* @修改内容 TODO
* @version V1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:test.xml"})
@TransactionConfiguration(defaultRollback = true)
public class SpringBaseTestCase extends
AbstractTransactionalJUnit4SpringContextTests {

}

3、测试类继承公共类

package com.main.test.testcase.service;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.sql.Timestamp;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.main.entity.User;
import com.main.service.UserService;
import com.scorpion.test.util.SpringBaseTestCase;

/**
* @author ZJ
* @作用 为service编辑test case
* @创建日期 2013-10-11下午05:58:06
* @修改人
* @修改日期
* @修改内容 TODO
* @version V1.0
*/
public class UserServiceImplTest extends SpringBaseTestCase{

/**
* @Field userService.
*/
@Autowired
private UserService userService;

/**
* @Description: 初始化测试环境
* @throws Exception
* java.lang.exception.
*/
@Before
public void setUp() throws Exception {
}

/**
* @Description: 测试完后清理现场
* @throws Exception
* java.lang.exception.
*/
@After
public void tearDown() throws Exception {
}

/**
* @Description: 增加用户到数据库
*/
@Test
public void saveUser(){
User user = new User();
user.setuName("zhongjie");
user.setPwd("123456");
user.setCreateTime(new Timestamp(System.currentTimeMillis()));
userService.addUser(user);
}

/**
* @Description: 根据用户名查找用户
*/
@Test
public void getUserByName(){
User user = new User();
user.setuName("zhongjie");
user.setPwd("123456");
user.setCreateTime(new Timestamp(System.currentTimeMillis()));
userService.addUser(user);

User gUser = userService.getUser(user.getuName());
assertNotNull(gUser);
assertEquals(user.getPwd(),gUser.getPwd());
}

}


  总结:StrutsSpringTestCase这种针对struts、spring做测试的,相对适合ssh架构,但其有一点需要注意的地方,就是对spring的配置是直接操作数据库的,所以在做一些增删改的测试时,需要增加rollback,或是为测试准备一个跟正式环境一样运行的数据库,以模拟测试。(个人认为这一点很不好,也不方便)目前为止,还没有找到像ejbunit那样,使用excel文档来模拟生成数据库进而对其进行数据操作的方法,这一点会继续跟进。