junit-service工程解析
之前对项目中的测试工程了解的不够透彻,蹭着项目上线后的闲暇时间总结一下。
maven配置
项目中写了一个专门的测试工程,以jar包形式提供出去。通过maven进行管理,maven配置:
<artifactId>junit-service</artifactId>
<packaging>jar</packaging>
<version>${junitServiceVersion}</version>
其他工程调用时只需要在对应的maven下进行配置就行了。maven配置:
<!--运行junit单元测试类需要的-->
<dependency>
<groupId>com.myph</groupId>
<artifactId>junit-service</artifactId>
<version>${junitServiceVersion}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
junit-service工程目录结构
工程解析
BaseServiceTest.java代码
package com.myph.test;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import org.junit.runner.RunWith;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.util.ResourceUtils;
import java.io.FileNotFoundException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:/spring/applicationContext-*.xml",})
@TransactionConfiguration(transactionManager = "transactionManager")
public class BaseServiceTest {
static {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(lc);
lc.reset();
try {
try {
configurator.doConfigure(ResourceUtils.getFile("classpath:logback.xml"));//加载logback配置文件
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} catch (JoranException e) {
e.printStackTrace();
}
//PropertyConfigurator.configure("/home/lhy/Workspaces/MyEclipse_data/gooddeep/src/main/java/config/log4j.properties");//加载logj配置文件
}
}
@RunWIth(SpringJunit4ClassRunner.class)
这种写法是为了让测试在Spring容器环境下执行。junit和spring一起使用时需要这样写。
@ContextConfiguration(locations = {"classpath*:/spring/applicationContext-*.xml",})
用来指定加载的Spring配置文件的位置,这样写的话会加载applicationContext-base.xml、applicationContext-common.xml、applicationContext-dao.xml。
@TransactionConfiguration(transactionManager=”transactionManager”)读取Spring配置文件中名为transactionManager的事务配置,defaultRollback为事务回滚默认设置。该注解是可选的,可使用@Transactional与@Rollback配合完成事务管理。当然也可以使用@Transactional与@TransactionConfiguration配合。
@Transactional开启事务。可放到类或方法上,类上作用于所有方法。
@Rollback事务回滚配置。只能放到方法上。
这里我们没有用defaultRollback配置,可以看下这个例子:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:config/applicationContext-*.xml", "classpath:services/ext/service-*.xml" })
@Transactional
@TransactionConfiguration(transactionManager = "transactionManager")
//@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class UserServiceTest {
@Resource
private IUserService userService;
@Test
// @Transactional
public void testAddOpinion1() {
userService.downloadCount(1);
System.out.println(1);
}
@Test
@Rollback(false)
public void testAddOpinion2() {
userService.downloadCount(2);
System.out.println(2);
}
}
中间部分的代码主要是加载logback文件。
logback使用
applicationContext-base.xml解析
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="configLoader"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/config/*.properties</value>
</list>
</property>
</bean>
<!-- <mvc:annotation-driven/>相当于注册了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter两个bean,配置一些messageconverter。即解决了@Controller注解的使用前提配置 -->
<context:component-scan base-package="com.myph">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
<bean id="configLoader"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/config/*.properties</value>
</list>
</property>
</bean>
这一段的作用是在Spring容器启动时,使用内置bean对属性文件信息进行加载。属性信息加载后有两种使用方法:
1)在其它bean定义中直接根据属性信息的key引用value。例如:
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxActive}"/>
<property name="minIdle" value="${redis.pool.minIdle}"/>
<property name="maxIdle" value="${redis.pool.maxIdle}"/>
<property name="maxWaitMillis" value="${redis.pool.maxWait}"/>
<property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
<property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
<property name="testWhileIdle" value="${redis.pool.testWhileIdle}"/>
</bean>
2)在代码中获取配置的属性信息,利用注解将代码中需要使用的属性信息注入。例如:
@Value("${sms_url}")
private String sms_url;
@Value("${isSend}")
private boolean isSend;// 默认false:代表发送短信 true:不发送短信
<context:component-scan base-package="com.myph">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
这一段的作用是开启spring注解,同时过滤掉@Controller注解。
applicationContext-common.xml解析
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxActive}"/>
<property name="minIdle" value="${redis.pool.minIdle}"/>
<property name="maxIdle" value="${redis.pool.maxIdle}"/>
<property name="maxWaitMillis" value="${redis.pool.maxWait}"/>
<property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
<property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
<property name="testWhileIdle" value="${redis.pool.testWhileIdle}"/>
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="jedisPoolConfig"/>
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="password" value="${redis.pasaword}"/>
<property name="database" value="${redis.db.index}"/>
</bean>
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory"/>
</bean>
</beans>
applicationContext-common.xml文件是对Jedis进行设置,Jedis 是 Redis 官方首选的 Java 客户端开发包。
applicationContext-dao.xml解析
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="proxyFilters">
<list>
<bean id="log-filter" class="com.alibaba.druid.filter.logging.Slf4jLogFilter" />
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
<property name="slowSqlMillis" value="${slow.sql.millis}"/>
<property name="logSlowSql" value="${slow.sql.enable}"/>
<property name="mergeSql" value="${slow.sql.merge}"/>
</bean>
<bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
<property name="dbType" value="${wall.db.type}"/>
</bean>
</list>
</property>
<property name="initialSize" value="${jdbc.initial_size}"/>
<property name="maxActive" value="${jdbc.max_active}"/>
<property name="minIdle" value="${jdbc.min_idle}"/>
<property name="maxWait" value="${jdbc.max_wait}"/>
<property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"/>
<property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTime}"/>
<property name="validationQuery" value="SELECT 'x'"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml" />
<property name="mapperLocations" value="classpath*:/mybatis/mapper/**/*.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.myph.**.dao" />
<property name="markerInterface" value="com.myph.common.rom.IBaseMapper" />
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"
destroy-method="clearCache">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
applicationContext-dao.xml是对数据库进行设置,这里用了druid数据库连接池。
junit-service的使用
使用时,测试类继承BaseServiceTest,测试方法上加上@Test注解即可使用。