1:
我在web-inf下有个bean的配置片段
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/persist/jdbc.properties</value>
</list>
</property>
</bean>
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>/WEB-INF/persist/sqlMapConfig.xml</value>
</property>
</bean>
如果单元测试
使用
FileSystemXmlApplicationContext(locs)获得ApplicationContext,但是上面配置片段中的路径会找不到.
2:
把你的bean.xml移到classpath下面(classes目录),比如com.javaeye这个package下面。
那么web.xml里面可以这样写:
单元测试用ClassPathXmlApplicationContext
那些jdbc property和ibatis mapping文件的location也可以写成
classpath: xxx.properties
这样的好处是可以打一个jar包就把所有的东东就包含进去了......
3:
又学了一招
但是按照我的目录,配置文件放外部比较舒服点,测试只好写麻烦点拉
但是我不晓得怎么在测试里控制 数据库事务.比如下面的UserAccountDaoImpTest.testGetInsertUpdateDeleteAccount()
用SqlMapClient.startTranscation() commitTranscation()...会有问题
通过的测试
4:
做spring dao的单元测试的确会遇到事务、OpenSessionInView等问题,spring论坛很早就谈论了这些问题。建议直接去他的官方论坛查找,这样比较实际些。
下面给出一些利用dbunit的一些代码片断
基类:SpringTestCase
继承DatabaseTestCase需要复写几个方法
getConnection方法是dbunit得到数据库连接的方法,这其中我除了设置设置了数据库属性为Oracle,因为默认dbunit不会去设置,具体文档dbunit写的很详细
测试环境所需的数据源、数据文件,数据库属性我都用properties文件在外部设置,所以会出现props.getProperty(APP_DATASET)的语句,这不是必须的。你完全可以去掉这种语句。
getDataSet方法设置你的测试数据源,也就是数据文件。这里我设置的是xml格式的数据文件。
以后凡是要测试所有的Dao都继承自该基类。这样你就不用操心数据污染问题了。
至于测试中的事务问题,我就不多罗嗦了,贴出代码。大家一看就知道如何在测试中使用该类。
如果你使用了OpenSessionInView的话,可能需要模仿这种环境以避免测试环境下的懒加载异常。例如测试Web Action。那么测试类只需要继承自下面的类即可。
我在web-inf下有个bean的配置片段
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/persist/jdbc.properties</value>
</list>
</property>
</bean>
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>/WEB-INF/persist/sqlMapConfig.xml</value>
</property>
</bean>
如果单元测试
使用
FileSystemXmlApplicationContext(locs)获得ApplicationContext,但是上面配置片段中的路径会找不到.
2:
alin_ass 写道: |
我去试下,您有现成的测试代码吗? 我的结构是这样的 webapp | |--web-inf .....|---bean1.xml .....|---bean2.xml .....|---bean3.xml .....|---classes ................|---MyTestCase1.class |
把你的bean.xml移到classpath下面(classes目录),比如com.javaeye这个package下面。
那么web.xml里面可以这样写:
xml代码: |
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:/com/javaeye/bean1.xml, classpath:/com/javaeye/bean2.xml </param-value> </context-param> |
单元测试用ClassPathXmlApplicationContext
java代码: |
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[] {"com/javaeye/bean1.xml", "com/javaeye/bean2.xml"}); |
那些jdbc property和ibatis mapping文件的location也可以写成
classpath: xxx.properties
这样的好处是可以打一个jar包就把所有的东东就包含进去了......
3:
又学了一招
但是按照我的目录,配置文件放外部比较舒服点,测试只好写麻烦点拉
但是我不晓得怎么在测试里控制 数据库事务.比如下面的UserAccountDaoImpTest.testGetInsertUpdateDeleteAccount()
用SqlMapClient.startTranscation() commitTranscation()...会有问题
通过的测试
java代码: |
public class DaoImpTest extends TestCase { protected final void initDaoImp(SqlMapClientDaoSupport daoImp) throws Exception { String classesDirLoc = ClassLoader.getSystemResource("").getFile(); File webinfDir = new File(classesDirLoc).getParentFile(); //init data source InputStream is = new FileInputStream(new File(webinfDir, "jdbc.properties")); Properties jdbcProperties = new Properties(); jdbcProperties.load(is); BasicDataSource basicDS = new BasicDataSource(); basicDS.setDriverClassName(jdbcProperties .getProperty("jdbc.driverClassName")); basicDS.setUrl(jdbcProperties.getProperty("jdbc.url")); basicDS.setUsername(jdbcProperties.getProperty("jdbc.username")); basicDS.setPassword(jdbcProperties.getProperty("jdbc.password")); DataSource ds = basicDS; //init sqlMapClient Reader reader = new FileReader(new File(webinfDir, "sqlMapConfig.xml")); SqlMapClient sqlMapClient = new XmlSqlMapClientBuilder() .buildSqlMap(reader); //init daoImp daoImp.setDataSource(ds); daoImp.setSqlMapClient(sqlMapClient); } } |
java代码: |
public class UserAccountDaoImpTest extends DaoImpTest { private UserAccountDao dao; protected void setUp() throws Exception { UserAccountDaoImp daoImp = new UserAccountDaoImp(); this.initDaoImp(daoImp); this.dao = daoImp; } public void testGetInsertUpdateDeleteAccount() {...} } |
java代码: |
public class UserAccountDaoImp extends SqlMapClientDaoSupport implements UserAccountDao {...} |
4:
做spring dao的单元测试的确会遇到事务、OpenSessionInView等问题,spring论坛很早就谈论了这些问题。建议直接去他的官方论坛查找,这样比较实际些。
下面给出一些利用dbunit的一些代码片断
基类:SpringTestCase
java代码: |
abstract public class SpringTestCase extends DatabaseTestCase |
继承DatabaseTestCase需要复写几个方法
getConnection方法是dbunit得到数据库连接的方法,这其中我除了设置设置了数据库属性为Oracle,因为默认dbunit不会去设置,具体文档dbunit写的很详细
测试环境所需的数据源、数据文件,数据库属性我都用properties文件在外部设置,所以会出现props.getProperty(APP_DATASET)的语句,这不是必须的。你完全可以去掉这种语句。
java代码: |
protected IDatabaseConnection getConnection() throws Exception { DataSource ds = (DataSource) getBean(props.getProperty(BEAN_DATASOURCE)); IDatabaseConnection conn = new DatabaseConnection(ds.getConnection(), props.getProperty(TEST_SCHEMA)); conn.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new OracleDataTypeFactory()); return conn; } |
getDataSet方法设置你的测试数据源,也就是数据文件。这里我设置的是xml格式的数据文件。
java代码: |
protected IDataSet getDataSet() throws Exception { try { InputStream in = new FileInputStream(props.getProperty(APP_DATASET)); return new XmlDataSet(in); } catch (FileNotFoundException ex) { log.error(ex); throw new SpringTestCaseException(ex); } } |
以后凡是要测试所有的Dao都继承自该基类。这样你就不用操心数据污染问题了。
至于测试中的事务问题,我就不多罗嗦了,贴出代码。大家一看就知道如何在测试中使用该类。
java代码: |
package com.idealbiz.test; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.orm.hibernate.HibernateTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import net.sf.hibernate.SessionFactory; /** * $Id: HibernateTransactionUtils.java,v 1.9 2004/09/03 17:23:14 denis Exp $ * Class HibernateTransactionUtils * * <p> Shanghai Ideal Information Industry (Group) Co.,Ltd.</p> * @author denis <tt>deniswang@sina.com</tt> * 2004-9-2 17:50:02 */ public class HibernateTransactionUtils { private static final Log log = LogFactory .getLog(HibernateTransactionUtils.class); private PlatformTransactionManager ptm; private TransactionStatus status; private static HibernateTransactionUtils transactionUtils; protected HibernateTransactionUtils(SessionFactory sessionFactory) { log.info("Initialize HibnernateTransactionManager ..."); ptm = new HibernateTransactionManager(sessionFactory); } public static HibernateTransactionUtils getNewInstance(SessionFactory sessionFactory) { if (transactionUtils == null) { transactionUtils = new HibernateTransactionUtils(sessionFactory); } return transactionUtils; } public void beginTransaction() { log.info("begin Transaction ..."); status = ptm.getTransaction(new DefaultTransactionDefinition()); } public void rollbackTransaction() { if (status != null) { log.info("rollback Transaction ..."); ptm.rollback(status); } else { throw new IllegalStateException("Transaction status incorrect."); } } public void commitTransaction() { if (status != null) { log.info("commit Transaction ..."); ptm.commit(status); } else { throw new IllegalStateException("Transaction status incorrect."); } } } |
如果你使用了OpenSessionInView的话,可能需要模仿这种环境以避免测试环境下的懒加载异常。例如测试Web Action。那么测试类只需要继承自下面的类即可。
java代码: |
package com.idealbiz.test; import org.springframework.orm.hibernate.SessionFactoryUtils; import org.springframework.orm.hibernate.SessionHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; /** * $Id: OpenSessionInTestCase.java,v 1.2 2004/09/08 07:59:06 denis Exp $ * Class OpenSessionInTestCase * * <p> Shanghai Ideal Information Industry (Group) Co.,Ltd.</p> * @author denis <tt>deniswang@sina.com</tt> * 2004-9-7 16:47:53 */ public class OpenSessionInTestCase extends SpringTestCase { protected final static String SESSION_FACTORY_NAME = "sessionFactory"; private SessionFactory sessionFactory = null; public OpenSessionInTestCase(){ super(); } public OpenSessionInTestCase(String name) { super(name); } protected void setUp() throws Exception { super.setUp(); sessionFactory = getSessionFactory(); Session session = SessionFactoryUtils.getSession(sessionFactory, true); TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); } protected void tearDown() throws Exception { SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory); SessionFactoryUtils.closeSessionIfNecessary(sessionHolder.getSession(), sessionFactory); super.tearDown(); } public SessionFactory getSessionFactory() { if (sessionFactory == null) { sessionFactory = (SessionFactory) getBean(SESSION_FACTORY_NAME); } return sessionFactory; } } |