用Cactus来测试J2ee应用

来源:qqread 作者: 2007-12-03 出处:pcdog.com

.net  apache  java  jsp  mysql  
下一页 1 2 

韩伟 (java_cn@21cn.com)
北京某公司系统分析员
2002 年 8 月

junit是当前最流行的测试框架,它能够让开发人员很方便的编写测试单元,可以使他们"放心"地开发。但是现在很多的应用都是基于j2ee的,代码都是在服务器端的容器里面运行,这个使测试带来了一些麻烦。对于普通的jsp,servlet用junit来测试好像已经不是那么方便,对于ejb来说,特别是2.0版本,很多接口都是local Interface,没有办法进行分布式的测试。那么我们如何进行这些代码的测试呢?Apache为我们提供了一个强大的工具 Cactus!它是一套简单,易于使用的服务器端测试框架,可以使开发人员很轻松的测试服务器端的程序,他们会说:"哦,就是这么简单"。Cactus是Junit的一个扩展,但是它又和Junit有一些不同。Cactus的测试分为三种不同的测试类别,JspTestCase,ServletTestCase,FilterTestCase,而不是像Junit就一种TestCase。Cactus的测试代码有服务器端和客户端两个部分,他们协同工作。那我们为什么不用Junit来做测试呢?主要有一下几个理由:

  1. EJB2.0中的Local interface ,不允讯远程调用。用Junit不好测试,而Cactus的redirector位于服务器端,可以和EJB运行在一个容器中,这使得它可以直接访问Local Interface。
  2. 一般EJB或者servlet,jsp都是运行在服务器上,如果你使用junit测试的话,你的测试是在客户端,这使的运行环境和测试环境处于不同的系统环境中,这个有时候会不同的测试结果。
  3. 在一个EJB的应用中,一般都会有一些前端应用来访问EJB,例如:jsp,servlet,javabean。这就意味着你需要一个测试框架来测试这些前端的组件。Cactus提供了所有这些组件的测试方法。哦,太棒了。
  4. Cactus和ant很好的结合在一起,可以很容易的完成自动化测试,减少了很多工作量。当然,junit也提供这样的支持。

前面是对cactus作了一个大致的介绍,接下来我们用一个实际的例子来运用一下这个强大的测试框架。首先我们需要一个被测试的对象,在这里我们选用ejb2.0 CMP.我们做一个简单的用户管理。一下就一些主要的代码,来进行一些分析。

UserHome.java

package usersystem;

import javax.ejb.*;
import java.util.*;

public interface UserHome extends javax.ejb.EJBLocalHome {
  public User create(String name, String password) throws CreateException;
  public Collection findAll() throws FinderException;
    public User findByPrimaryKey(String name) throws FinderException;
}
User.java
package usersystem;

import javax.ejb.*;
import java.util.*;
public interface User extends javax.ejb.EJBLocalObject {
  public String getName();
  public void setPassword(String password);
  public String getPassword();
  public void setUserInfo(UserInfo userInfo);
  public UserInfo getUserInfo();
  public void setName(String name);
}

UserInfoHome.java
package usersystem;

import javax.ejb.*;
import java.util.*;

public interface UserInfoHome extends javax.ejb.EJBLocalHome {
    public UserInfo create(String name, String email, String address, String tel) throws 

CreateException;
    public UserInfo findByPrimaryKey(String name) throws FinderException;
}

这里有两个entity Bean用来创建用户信息。他们之间的关系在xml部署描述文件中描述,他们是1对1的关系。

UserManagerLocal.java

package usersystem;

import javax.ejb.*;
import java.util.*;

public interface UserManagerLocal extends javax.ejb.EJBLocalObject {
    public void addUser(String name, String password, String email, String address, String tel);
    public Collection findAll() ;
    public void delAll();
    public void delByName(String name);
    public User findByName(String name) ;
}

UserManagerBean.java

package usersystem;

import javax.ejb.*;
import javax.rmi.PortableRemoteObject;
import javax.naming.*;
import java.util.*;

public class UserManagerBean implements SessionBean {
  SessionContext sessionContext;
  public void ejbCreate() throws CreateException {
    /**@todo Complete this method*/
  }

  public void ejbRemove() {
    /**@todo Complete this method*/
  }
  public void ejbActivate() {
    /**@todo Complete this method*/
  }
  public void ejbPassivate() {
    /**@todo Complete this method*/
  }
  public void setSessionContext(SessionContext sessionContext) {
    this.sessionContext = sessionContext;
  }

  /**
   * 添加用户
   * @param name 用户姓名
   * @param password 密码
   * @param email 电子邮件
   * @param address 地址
   * @param tel 电话
   */
  public void addUser(String name, String password, String email, String address, String tel) {

      try{
          UserHome userHome=getUserHome();
          User user=userHome.create(name,password)  ;  //create user entity
          UserInfoHome userInfoHome=getUserInfoHome();
          UserInfo userInfo=userInfoHome.create(name,email,address,tel) ;// create userinfo 

entity
          user.setUserInfo(userInfo) ;


      }catch(Exception e){

          throw new javax.ejb.EJBException (e.toString());
      }


  }

  /**
   * 返回UserHome接口
   * @return userHome
   */
  private UserHome getUserHome(){

    try {
        javax.naming.InitialContext ctx=new javax.naming.InitialContext ();
          Object ref = ctx.lookup("User");
          //cast to Home interface
          UserHome userHome = (UserHome) PortableRemoteObject.narrow(ref, UserHome.class);
          return userHome;
    }
    catch (ClassCastException ex) {
        ex.printStackTrace() ;
        return null;
    }catch (NamingException ex) {
        ex.printStackTrace() ;
        return null;
    }

  }

  /**
   * 返回UserInfoHome接口
   * @return
   */
  private UserInfoHome getUserInfoHome(){

    try {
        javax.naming.InitialContext ctx=new javax.naming.InitialContext ();
          Object ref = ctx.lookup("UserInfo");
          //cast to Home interface
          UserInfoHome userInfoHome = (UserInfoHome) PortableRemoteObject.narrow(ref, 

UserInfoHome.class);
          return userInfoHome;
    }
    catch (ClassCastException ex) {
        throw new EJBException();
    }catch (NamingException ex) {
        throw new EJBException(ex.toString());
    }

  }



  /**
   * 返回所有用户记录
   * @return c
   * @throws javax.ejb.FinderException
   */
  public java.util.Collection findAll() {
    Collection c = null;
    try {
        UserHome uh=this.getUserHome() ;
          c=uh.findAll() ;
    }
    catch (FinderException ex) {
            throw new javax.ejb.EJBException ();
    }
      return c;
  }

    /**
     * 删除所有记录
     */
    public void delAll(){
        try {
            UserHome u=getUserHome();

            java.util.Collection c=u.findAll() ;
            java.util.Iterator i=c.iterator() ;
            while(i.hasNext() ){
                u.remove(((User)i.next()).getName()) ;
            }
        }
        catch (Exception ex) {
            throw new EJBException(ex.toString());
        }
    }

    /**
     * 根据用户名删除记录
     * @param name
     */
    public void delByName(String name) {
        try {
            User user=findByName(name);
            UserHome uh=getUserHome();
            uh.remove(user.getName()) ;
        }
        catch (Exception ex) {
            throw new javax.ejb.EJBException (ex.toString());
        }
    }

    /**
     * 通过用户名查找用户记录
     * @param name
     * @return
     */
    public User findByName(String name) {
        try {
            UserHome uh=this.getUserHome() ;
            User user=(User)uh.findByPrimaryKey(name) ;
            UserHome u=this.getUserHome() ;
            User uu=u.findByPrimaryKey(name)  ;
            return user;
        }
        catch (FinderException ex) {
            throw new EJBException(ex.toString());
        }

    }

}

usermanagerbean是一个session bean ,它主要是对user的管理,和客户端通讯,其实就是session facade模式 。代码里面有注释,这里就不多叙述了。

ejb-jar.xml 部署文件描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" 

"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
    <enterprise-beans>
        <session>
            <display-name>UserManager</display-name>
            <ejb-name>UserManager</ejb-name>
            <local-home>usersystem.UserManagerLocalHome</local-home>
            <local>usersystem.UserManagerLocal</local>
            <ejb-class>usersystem.UserManagerBean</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
            <ejb-local-ref>
                <description />
                <ejb-ref-name>User</ejb-ref-name>
                <ejb-ref-type>Entity</ejb-ref-type>
                <local-home>usersystem.UserHome</local-home>
                <local>usersystem.User</local>
                <ejb-link>User</ejb-link>
            </ejb-local-ref>
            <ejb-local-ref>
                <description />
                <ejb-ref-name>UserInfo</ejb-ref-name>
                <ejb-ref-type>Entity</ejb-ref-type>
                <local-home>usersystem.UserInfoHome</local-home>
                <local>usersystem.UserInfo</local>
                <ejb-link>UserInfo</ejb-link>
            </ejb-local-ref>
        </session>
        <entity>
            <display-name>User</display-name>
            <ejb-name>User</ejb-name>
            <local-home>usersystem.UserHome</local-home>
            <local>usersystem.User</local>
            <ejb-class>usersystem.UserBean</ejb-class>
            <persistence-type>Container</persistence-type>
            <prim-key-class>java.lang.String</prim-key-class>
            <reentrant>False</reentrant>
            <cmp-version>2.x</cmp-version>
            <abstract-schema-name>User</abstract-schema-name>
            <cmp-field>
                <field-name>name</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>password</field-name>
            </cmp-field>
            <primkey-field>name</primkey-field>
            <query>
                <query-method>
                    <method-name>findAll</method-name>
                    <method-params />
                </query-method>
                <ejb-ql>select Object(theUser) from User as theUser</ejb-ql>
            </query>
        </entity>
        <entity>
            <display-name>UserInfo</display-name>
            <ejb-name>UserInfo</ejb-name>
            <local-home>usersystem.UserInfoHome</local-home>
            <local>usersystem.UserInfo</local>
            <ejb-class>usersystem.UserInfoBean</ejb-class>
            <persistence-type>Container</persistence-type>
            <prim-key-class>java.lang.String</prim-key-class>
            <reentrant>False</reentrant>
            <cmp-version>2.x</cmp-version>
            <abstract-schema-name>UserInfo</abstract-schema-name>
            <cmp-field>
                <field-name>name</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>email</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>address</field-name>
            </cmp-field>
            <cmp-field>
                <field-name>tel</field-name>
            </cmp-field>
            <primkey-field>name</primkey-field>
        </entity>
    </enterprise-beans>
    <relationships>
        <ejb-relation>
            <ejb-relation-name>userInfo-user</ejb-relation-name>
            <ejb-relationship-role>
                <description>userInfo</description>
                <ejb-relationship-role-name>UserInfoRelationshipRole</ejb-relationship-role-name>
                <multiplicity>One</multiplicity>
                <cascade-delete />
                <relationship-role-source>
                    <description>userInfo</description>
                    <ejb-name>UserInfo</ejb-name>
                </relationship-role-source>
                <cmr-field>
                    <description>user</description>
                    <cmr-field-name>user</cmr-field-name>
                </cmr-field>
            </ejb-relationship-role>
            <ejb-relationship-role>
                <description>user</description>
                <ejb-relationship-role-name>UserRelationshipRole</ejb-relationship-role-name>
                <multiplicity>One</multiplicity>
                <relationship-role-source>
                    <description>user</description>
                    <ejb-name>User</ejb-name>
                </relationship-role-source>
                <cmr-field>
                    <description>userInfo</description>
                    <cmr-field-name>userInfo</cmr-field-name>
                </cmr-field>
            </ejb-relationship-role>
        </ejb-relation>
    </relationships>
    <assembly-descriptor>
        <container-transaction>
            <method>
                <ejb-name>User</ejb-name>
                <method-name>*</method-name>
            </method>
            <trans-attribute>Required</trans-attribute>
        </container-transaction>
        <container-transaction>
            <method>
                <ejb-name>UserManager</ejb-name>
                <method-name>*</method-name>
            </method>
            <trans-attribute>Required</trans-attribute>
        </container-transaction>
        <container-transaction>
            <method>
                <ejb-name>UserInfo</ejb-name>
                <method-name>*</method-name>
            </method>
            <trans-attribute>Required</trans-attribute>
        </container-transaction>
    </assembly-descriptor>
</ejb-jar>


下一页 1 2 
上一篇:从森林到咖啡馆——书评《J2EE设计开发编程指南》
下一篇:最重要的 10 几个 J2EE 最佳实践