- 浏览: 926372 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
lgh1992314:
pkptzx 写道额,误人子弟...CaseInsensiti ...
关于commons dbutils组件的一个小缺陷分析 -
yk0025:
擦,有才,这是原创吗?
《神雕瞎驴》,金庸看后哭了^-^ -
hzxlb910:
没跑起来Exception in thread "m ...
Socket 群聊 -
pkptzx:
额,误人子弟...CaseInsensitiveMap是apa ...
关于commons dbutils组件的一个小缺陷分析 -
swearyd7:
Fiddler 宝典
用Cactus来测试J2ee应用 | ||
韩伟 (java_cn@21cn.com) Junit是当前最流行的测试框架,它能够让开发人员很方便的编写测试单元,可以使他们"放心"地开发。但是现在很多的应用都是基于j2ee的,代码都是在服务器端的容器里面运行,这个使测试带来了一些麻烦。对于普通的jsp,servlet用Junit来测试好像已经不是那么方便,对于EJB来说,特别是2.0版本,很多接口都是Local Interface,没有办法进行分布式的测试。那么我们如何进行这些代码的测试呢?Apache为我们提供了一个强大的工具 Cactus!它是一套简单,易于使用的服务器端测试框架,可以使开发人员很轻松的测试服务器端的程序,他们会说:"哦,就是这么简单"。Cactus是Junit的一个扩展,但是它又和Junit有一些不同。Cactus的测试分为三种不同的测试类别,JspTestCase,ServletTestCase,FilterTestCase,而不是像Junit就一种TestCase。Cactus的测试代码有服务器端和客户端两个部分,他们协同工作。那我们为什么不用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 (c) 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 (c) 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的测试方法,一共一个界面, 但是没有什么太大的意义。 到此我们介绍了所有的主要方法。最后我们谈谈如何运行这个测试。
哈哈~~,终于完成了所有的工作,我们可以看看运行结果,"哦,不",居然出现了一个Error,那就是你的程序出现了问题,仔细看看吧,测试是不会骗你的 :) 。 以上代码在 win2000+JBOSS3.0+MySql MAX 3.24+Cactus1.3上运行成功。 韩伟,任北京某公司系统分析员,主要从事j2ee发面的开发,对设计模式,Java,软件工程很感兴趣。您可以通过email:java_cn@21cn.com跟他取得联系。 |
相关推荐
基于Cactus的JSP页面测试及代码自动生成器,张震,杨正球,单元测试的自动化越来越受到软件开发企业的重视,但J2EE应用程序实现单元测试自动化却存在一定困难。本文指出原有的测试框架应用��
Cactus是一个基于JUnit框架的简单测试框架,用来单元测试服务端Java代码。Cactus框架的主要目标是能够单元测试服务端的使用Servlet对象的Java方法如HttpServletRequest,HttpServletResponse,HttpSession等
CACTUS
通过Ant Cactus DbUnit StrutsTest测试组件对一个简单应用程序进行全面的测试
通过Ant Cactus DbUnit StrutsTest测试组件对一个简单应用程序进行全面的测试
通过Ant Cactus DbUnit StrutsTest测试组件对一个简单应用程序进行全面的测试
The Cactus project is pleased to announce the release of version 1.7.2. Cactus is a unit testing framework for testing server side java code.
cactus-1.8.1-bin.zip 对java web 进行单元测试
cactus-report.xsl cactus-report.xsl cactus-report.xsl
个人作品 6-Cactus.rar 需要的同学可以看看
在React中建立的一个应用框架和设计系统。 。 模组 仙人掌框架 仙人掌I18n库 仙人掌图标 theme-仙人掌UI主题 web-仙人掌Web UI组件 示例应用 -作为基本Web应用的功能的通用实现。 -探索比标准更深入地使用组件。...
jakarta-cactus-12-1.7.1.rar
请vs2013打开或者2015,用了.net4.5.2 ,Cactus1.5.x
有向cactus判定的证明,一个有向图是有向Cactus的三个充要条件。
Cactus:设计师设计的静态站点生成器。使用Python和Django模板。
NULL 博文链接:https://whythiszhao.iteye.com/blog/966494
资源分类:Python库 所属语言:Python 资源全名:Cactus-3.1.0.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
包括探索JUnit的核心、软件测试原则、测试覆盖率与开发、使用stub进行粗粒度测试...使用Cactus进行服务器端的Java测试、测试JSF应用程序、测试OSGi组件、测试数据库访问、测试基于JPA的应用程序、JUnit的其他用法等内容...
一个变态的jar包,按照我当前的工程环境,应该在weblogic8底下,但就是找不到,所以只好在网上找了,记录在这里。 包含的类: org.apache.cactus.server.ServletTestRedirector
包括探索JUnit的核心、软件测试原则、测试覆盖率与开发、使用stub进行粗粒度测试...使用Cactus进行服务器端的Java测试、测试JSF应用程序、测试OSGi组件、测试数据库访问、测试基于JPA的应用程序、JUnit的其他用法等内容...