51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 5839|回复: 1

用cactus测试j2ee (转)

[复制链接]
  • TA的每日心情
    开心
    2023-11-23 10:57
  • 签到天数: 1681 天

    连续签到: 1 天

    [LV.Master]测试大本营

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

    EJB2.0中的Local interface ,不允讯远程调用。用Junit不好测试,而Cactus的redirector位于服务器端,可以和EJB运行在一个容器中,这使得它可以直接访问Local Interface。
    一般EJB或者servlet,jsp都是运行在服务器上,如果你使用junit测试的话,你的测试是在客户端,这使的运行环境和测试环境处于不同的系统环境中,这个有时候会不同的测试结果。
    在一个EJB的应用中,一般都会有一些前端应用来访问EJB,例如:jsp,servlet,javabean。这就意味着你需要一个测试框架来测试这些前端的组件。Cactus提供了所有这些组件的测试方法。哦,太棒了。
    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>

    接下来是访问EJB的客户端,我们用了一个servlet.

    ManaServlet.java
    package usersystem.servlet;

    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.*;
    import java.util.*;

    import usersystem.*;
    import javax.naming.*;
    import javax.ejb.*;
    import javax.ejb.*;
    import javax.ejb.*;

    /**
    * <p>Title: </p>
    * <p>Description: </p>
    * <p>Copyright: Copyright  2002</p>
    * <p>Company: </p>
    * @author unascribed
    * @version 1.0
    */

    public class ManaServlet extends HttpServlet {
    static final private String CONTENT_TYPE = "text/html; charset=GBK";
    private UserManagerLocalHome h=null;
    private UserManagerLocal uml=null;

    public void init() throws ServletException{

    try {
    h=getHome();
    uml=h.create() ;
    }
    catch (CreateException ex) {
    ex.printStackTrace() ;
    }
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws

    ServletException, IOException {

    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws

    ServletException, IOException {

    }

    public void addUser(HttpServletRequest request, HttpServletResponse response) throws

    javax.ejb.EJBException {
    String name=request.getParameter("name") ;
    String tel=request.getParameter("tel") ;
    String address=request.getParameter("address") ;
    String email=request.getParameter("email") ;
    String pass=request.getParameter("pass") ;
    uml.addUser(name,pass,email,address,tel) ;
    }
    public User findByName(String name) throws javax.ejb.EJBException {
    User u = null;

    u=uml.findByName(name) ;

    return u;
    }
    public java.util.Iterator findAll() throws javax.ejb.EJBException {
    java.util.Collection c=uml.findAll() ;
    return c.iterator() ;
    }

    public void delAll() throws javax.ejb.EJBException {
    uml.delAll() ;
    }
    public void delUser(String name) throws javax.ejb.EJBException {

    uml.delByName(name) ;

    }
    public UserManagerLocalHome getHome() {
    UserManagerLocalHome home = null;
    try {
    javax.naming.InitialContext ctx=new javax.naming.InitialContext ();
    home=(UserManagerLocalHome)ctx.lookup("UserManagerLocal") ;
    }
    catch (NamingException ex) {
    ex.printStackTrace() ;
    return null;
    }
    return home;
    }

    public void destroy() {
    }
    }

    这个servlet在doGet,doPost没有实现任何方法,这个不影响我们测试,我们要测试的只是这些public method. 我们的测试代码如下:

    package usersystem.test;

    /**
    * <p>Title: </p>
    * <p>Description: </p>
    * <p>Copyright: Copyright  2002</p>
    * <p>Company: </p>
    * @author unascribed
    * @version 1.0
    */
    import usersystem.servlet.*;

    import java.io.IOException;
    import java.net.URLDecoder;
    import java.util.Hashtable;

    import junit.framework.Test;
    import junit.framework.TestSuite;

    import org.apache.cactus.Cookie;
    import org.apache.cactus.ServletTestCase;
    import org.apache.cactus.WebRequest;
    import org.apache.cactus.WebResponse;
    import javax.ejb.*;
    import javax.servlet.*;

    import usersystem.*;

    public class ManaServletTest extends ServletTestCase{
    ManaServlet servlet=new ManaServlet();
    public ManaServletTest(String theName) {
    super(theName);
    }

    public void setUp(){

    try {
    servlet.init() ;
    }
    catch (ServletException ex) {
    ex.printStackTrace() ;
    this.fail() ;
    }
    }
    public void tearDown(){

    }
    public void beginAddUser(WebRequest theRequest)
    {
    theRequest.addParameter("name", "nameValue");
    theRequest.addParameter("pass","passValue") ;
    theRequest.addParameter("tel","telValue") ;
    theRequest.addParameter("address","addressValue") ;
    theRequest.addParameter("email","emailValue");

    }
    public void testAddUser() throws javax.ejb.EJBException{
    servlet.addUser(request,response) ;
    }
    public void testFindAll(){
    java.util.Iterator i=servlet.findAll() ;
    //assertEquals(null,i);
    boolean ok=false;
    while(i.hasNext() ){
    if(((User)i.next()).getName().equals("nameValue")) {
    ok=true;
    };
    }
    this.assertTrue(ok) ;
    }
    public void testFindByName() throws javax.ejb.EJBException {
    User u=servlet.findByName("nameValue") ;
    UserInfo ui=u.getUserInfo() ;
    this.assertEquals("email",ui.getEmail()) ;
    this.assertEquals("tel",ui.getTel()) ;
    this.assertEquals("nameValue",u.getName()) ;
    this.assertEquals("passValue",u.getPassword()) ;

    }

    public void testDel() throws javax.ejb.EJBException {

    servlet.delUser("nameValue8") ;

    }
    public void testDelAll() throws javax.ejb.EJBException {
    servlet.delAll() ;
    }

    public static void main(String[] theArgs)
    {
    junit.textui.TestRunner.main(new String[]{
    ManaServletTest.class.getName()});
    }
    public static Test suite()
    {

    return new TestSuite(ManaServletTest.class);
    }

    }

    public class ManaServletTest extends ServletTestCase 我们要测试的是一个servlet,所以我们继承ServletTestCase,如果你测试jsp的话,就继承JspTestCase.

    public ManaServletTest(String theName) {
    super(theName);
    }
      
    和junit一下,ServletTestCase不允许使用默认的构造函数,所以必须使用一个带参数的构造函数,并且调用 父类的构造函数。

    public void setUp(){

    try {
    servlet.init() ;
    }
    catch (ServletException ex) {
    ex.printStackTrace() ;
    this.fail() ;
    }
    }
    public void tearDown(){

    }
      
    setUp是在测试类运行时候首先被调用的办法,在这里可以进行一些数据初始化之类的工作。在这里我们调用了 servlet.init().

    在测试类运行的时候需要显式的调用servlet的init()方法。因为cactus在测试servlet的时候是实例化一个ser vlet的,不会调用inti(),而servlet enginer在调用的时候是会自动调用servlet的init()方法的。tearDown方 法在测试完成的时候运行,进行一些必要的数据处理,比如删除一些测试数据等,这里我们没有做任何工作。

    public void beginAddUser(WebRequest theRequest)
    {
    theRequest.addParameter("name", "nameValue");
    theRequest.addParameter("pass","passValue") ;
    theRequest.addParameter("tel","telValue") ;
    theRequest.addParameter("address","addressValue") ;
    theRequest.addParameter("email","emailValue");

    }
    public void testAddUser() throws javax.ejb.EJBException{
    servlet.addUser(request,response) ;
    }
      
    在Cactus中,你需要用testXXX来命名你的方法,这样Cactus会自动调用这个方法进行测。而BeingXXX则是在调 用test方法之前调用,也就是说在一个功能测试之前运行。这里我们现在beginAddUser中添加一些必要的参数 。WebRequest是Cactus提供的一个类,它允许你设置一些Http参数,如果你使用了 theRequest.addParameter("name","nameValue"),那么在servlet中你就可以用request.getParameter("name") 来取得name的值。当然还可以设置Cookie,Http Head参数。在testAddUser()方法中我们测试addUser方法,如 果测试有异常,则会产生EJBException,得到一个测试失败。

    public void testFindByName() throws javax.ejb.EJBException {
    User u=servlet.findByName("nameValue") ;
    UserInfo ui=u.getUserInfo() ;
    this.assertEquals("email",ui.getEmail()) ;
    this.assertEquals("tel",ui.getTel()) ;
    this.assertEquals("nameValue",u.getName()) ;
    this.assertEquals("passValue",u.getPassword()) ;

    }
      
    这个测试是测试根据用户名查找用户,之后你可以用assertEquals方法来测试返回的值是否正确。

    public static void main(String[] theArgs)
    {
    junit.textui.TestRunner.main(new String[]{
    ManaServletTest.class.getName()});
    }
      
    这里我们使用textui来运行我们的测试类,提供文本的测试信息,还有一个Swing的测试方法,一共一个界面, 但是没有什么太大的意义。

    到此我们介绍了所有的主要方法。最后我们谈谈如何运行这个测试。

    首先下载Cactus。
    把lib/下的jar文件加入到 web app的lib下。以及你客户端的classpath中,这是最保险的,虽然不是所有 的jar都用的着。
    设置你的Cactus.找到cactus.properties 文件,把它加入到客户端的classpath中。
    修改cactus.properties 文件,把http://localhost:8080/test 改成你相应的设置,test是你web应用的 名称。其他设置可以不变。
    修改服务器端web应用的配置,在web.xml中加入:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <filter>
    <filter-name>FilterRedirector</filter-name>
    <filter-class>org.apache.cactus.server.FilterTestRedirector</filter-class>
    </filter>

    <filter-mapping>
    <filter-name>FilterRedirector</filter-name>
    <url-pattern>/FilterRedirector</url-pattern>
    </filter-mapping>

    <servlet>
    <servlet-name>ServletRedirector</servlet-name>
    <servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class>
    </servlet>

    <servlet>
    <servlet-name>JspRedirector</servlet-name>
    <jsp-file>/jspRedirector.jsp</jsp-file>
    </servlet>

    <servlet-mapping>
    <servlet-name>ServletRedirector</servlet-name>
    <url-pattern>/ServletRedirector</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
    <servlet-name>JspRedirector</servlet-name>
    <url-pattern>/JspRedirector</url-pattern>
    </servlet-mapping>

    编译ejb和servlet,把EJB文件的jar,和servlet的war文件打包成 ear文件。
    发布你的ear文件到web application.
    运行本地的测试文件ManaServletTest.class

    该用户从未签到

    发表于 2005-4-6 09:12:10 | 显示全部楼层
    哪里有下载的?
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-3-29 17:29 , Processed in 0.073659 second(s), 28 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表