技术开发 频道

使用MockEJB测试SessionBean及数据库应用

【IT168 技术文档】

  J2EE应用中对于EJB的单元测试是很麻烦的,需要写完EJB后再打包、部署、测试出问题后再次修改、打包、部署……而打包、部署的时间往往是最浪费时间的,MockEJB可以帮助我们省略这2步,编译完成后即可运行,调试方法跟普通的Javabean类似。

  MockEJB其实模拟了一个mini J2EE容器,对ejb的mock操作都在该虚拟容器内部执行,能够满足绝大部分的EJB功能测试。为了更方便的使用MockEJB,我们可以对其中常用的绑定、部署功能进行封装。

import org.mockejb.OptionalCactusTestCase;
import org.mockejb.MockContainer;
import org.mockejb.SessionBeanDescriptor;
import org.mockejb.jndi.MockContextFactory;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.StringTokenizer;
 
import net.sf.hibernate.cfg.Configuration;
import net.sf.hibernate.SessionFactory;
import com.mockrunner.mock.ejb.
MockUserTransaction;
import junit.framework.TestCase;
 
/**
 * 使用MockEJB做测试时的辅助类,
 * 封装了常用的deploy和bind方法。
 * 用自己的测试类继承该抽象类。
 * <p/>
 * @author lucene
 * @version 1.0 2004-12-15 10:26:33
 */
public abstract class AbstractMockEJBTest
extends TestCase
{
 
    private Context context;
    private MockContainer mockContainer;
 
    /**
     * 初始化上下文环境。
     */
    protected void setUp() throws Exception
 {
        MockContextFactory.setAsInitial();
        context = new InitialContext();
        mockContainer =
  new MockContainer(context);
    }
 
    /**
     * 取得上下文环境
     *
     * @return 上下文环境
     */
    protected Context getContext()
 {
        return context;
    }
 
    /**
     * 把指定的SessionBean部署到
  Mock的容器环境中。
     *
     * @param jndi       JNDI名称
     * @param home       主接口
     * @param remote     远程接口
     * @param bean       实现类
     * @throws Exception
     */
    public void deploySessionBean
 (String jndi, Class home, Class
 remote, Class bean)
 throws Exception
 {
        SessionBeanDescriptor descriptor =
                new SessionBeanDescriptor
    (jndi, home, remote, bean);
        mockContainer.deploy(descriptor);
    }
 
    /**
     * 绑定数据源到上下文环境,
  这里默认提供的是Oracle的数据源,
     * 如果是MySQL,那么数据源就使用:
     * <code>com.mysql.jdbc.jdbc2.optional.
  MysqlDataSource</code>
     * 如果使用其他的数据库连结池来获取
  数据源则无需调用该方法。
     *
     * @param jndi       JNDI名称
     * @param url        JDBC URL
     * @param user       用户名
     * @param password   密码
     * @throws Exception
     */
    public void bindDataSource
 (String jndi, String url,
 String user, String password)
 throws Exception
 {
        oracle.jdbc.pool.OracleDataSource
  ds = new oracle.jdbc.pool
  .OracleDataSource();
        ds.setURL(url);
        if(user != null) ds.setUser(user);
        if(password != null)
  ds.setPassword(password);
        context.rebind(jndi, ds);
    }
 
    /**
     * 绑定<code>SessionFactory
  </code>到指定的JNDI名称
     * @param jndi       JNDI名称
     * @param cfgFiles   配置文件,
  中间用半角逗号隔开
     * @throws Exception
     */
    public void bindHibernate
 (String jndi, String cfgFiles)
 throws Exception
 {
        StringTokenizer st =
  new StringTokenizer(cfgFiles, ",");
        Configuration cfg = new Configuration();
        while(st.hasMoreTokens()) {
            String cfgFile = st.nextToken().trim();
            cfg.configure(cfgFile);
        }
        SessionFactory sf =
  cfg.buildSessionFactory();
        context.rebind(jndi, sf);
    }
 
    /**
     * 绑定事务处理到JNDI。
     *
     * @param trans     
  MockEJB的<code>MockUserTransaction</code>类
     * @throws Exception
     */
    public void bindTransaction
 (MockUserTransaction trans)
 throws Exception
 {
        if(trans == null)
  trans = new MockUserTransaction();
        context.rebind
  ("javax.transaction.UserTransaction",
  trans);
    }
 
    public void tearDown()
 {
   MockContextFactory.revertSetAsInitial();
    }
 
}

接下来的单元测试工作就很轻松啦,例如:

public class XXXUnitTest
extends AbstractMockEJBTest
{
    private ResourceServiceManager
 resServiceManager;
    private ResourceServiceManagerHome
 resServiceManagerHome;
 
    public void setUp() throws Exception
 {
        super.setUp();
        super.deploySessionBean
  (ResourceServiceManagerHome.JNDI_NAME,
  ResourceServiceManagerHome.class,
  ResourceServiceManager.class,
  ResourceServiceManagerBean.class);
        super.deploySessionBean
  (ResourceStockManagerHome.JNDI_NAME,
ResourceStockManagerHome.class,
ResourceStockManager.class,
ResourceStockManagerBean.class);
        super.bindDataSource("xxxx3ds",
  "jdbc:oracle:thin:
  @dbserver:1521:orcl", "user", "pass");
        super.bindHibernate
  ("hibernate/session_factory",
  "/xxx.cfg.xml, /xxx1.cfg.xml,
  /xxx2.cfg.xml");
        super.bindTransaction(mockTransaction);
        resServiceManagerHome =
  (ResourceServiceManagerHome)
  super.getContext().lookup
  (ResourceServiceManagerHome.JNDI_NAME);
        resServiceManager =
  resServiceManagerHome.create();
    }
    public void testXXXXXX()
 throws Exception {
        Collection result =
  resServiceManager.getXXXXXX();
        assertNotNull(result);
    }
}

  修改ResourceServiceManagerBean后不需要重新打包、部署EJB,直接编译,然后再次运行单元测试就能看到更新后的结果了。

0
相关文章