聊聊单元测试(二)——MockEJB

说明:本来想自己写一篇关于EJB测试的,也是使用MockEJB,但在搜集资料的时候,发现有两位美国佬已经写了一篇相关文章:


Alexander Ananiev拥有超过16年的使用各种语言和技术设计和开发计算机系统的经验。目前他在一家大型咨询公司担任架构师。

Eoin Woods已经在企业IT领域工作了15年,目前他在一家总部设在伦敦的全球投资银行中担任架构师。他一直在使用BEA的产品,从Tuxedo版本4开始。


他们俩写得挺全面的,感觉自己暂时无法超越,而且生怕自己误导了别人,只能先膜拜一下,然后把他俩的文章贴给大家了。顺便吐槽一句:谁说程序员干到30就完蛋了,人家不也干了将近20年,还有声有色的嘛。

----------------------------------------------------------------------------------------------------------

原文:


Enterprise JavaBean (EJB)是J2EE应用程序中的重要构件块,它为开发人员提供了一个支持服务定义、事件驱动处理和对象-关系持久性的标准框架。但是,使用EJB的开发 人员经常抱怨,EJB的使用使得应用程序的单元测试变得愈加复杂了。EJB依赖于容器的服务来运行,但是在对bean进行单元测试前将其部署到容器会减慢 这个过程,并使调试更为复杂。而最近测试驱动开发的流行又使这个问题加剧,这主要是由于其编写测试、编写生产代码以及这种方法所包含的重构所组成的快速周 期。


本文介绍了一种框架,MockEJB,它通过允许在EJB容器内部或外部测试EJB,从而为EJB的测试问题提供了一种可能的解决方案。构建于 现有的模仿对象(mock object)技术上的MockEJB允许开发人员在将EJB部署到容器进行集成测试之前,像对(EJB容器外的)普通Java对象那样,对EJB进行开 发和单元测试。在容器中,您可以使用MockEJB,通过控制bean的环境并允许模拟意外条件来对EJB进行充分测试。MockEJB的使用既使开发人 员的生活变得轻松,又使他们的生产力更高,还有助于实现比通常情况下更全面的测试覆盖范围。


EJB测试面临的挑战

Enterprise JavaBean (EJB)是许多大型J2EE应用程序中的重要构件块,它还被用于定义打包服务及其接口(使用会话bean)、创建事件处理程序(使用消息驱动 bean),有时候还用来提供持久性机制(通过实体bean)。EJB的许多功能和优点来自于EJB容器所提供的标准化的运行时环境和服务,包括自动化的 线程和内存管理、事务管理以及声明式安全性。但是,因为对容器的依赖性,EJB不能在容器外运行,所以当对EJB组件进行单元测试时,这个强大的运行时环 境也存在一些问题。我们如何能够轻松地对由一个应用服务器所提供的、运行在EJB容器内的东西进行单元测试呢?

  针对EJB的测试问题,人们提出了很多方法,从支持基本的容器外单元测试的简单EJB基类,到复杂的测试框架,比如Cactus(参见补充阅读一节),从而使得对运行在容器内的EJB进行单元测试成为可能。最近,作为对环境需求复杂的代码进行单元测试的一个可选方案,又出现了“模仿对象”方法,而MockEJB正是这种思想的特定于EJB开发的实现。

测试驱动开发和模仿对象

  在介绍MockEJB的细节之前,有必要先说明一下为它提供基础的思想和技术。

  测试驱动开发(TDD)是一种软件开发(而不是测试)方法,它将单元测试置于过程的中心地位。与编写大量代码、然后在允许的时间范围内进行尽可能多的单元测试的传统方式不同,TDD完全颠覆了这个过程,它为实现成功的测试而编写代码。其过程是高度可迭代的,包括一个快速周期:编写测试,然后编写 使测试成功所需的代码,最后重构以改进设计——如果新代码显示设计还不是最优的话。TDD的基本规则是,编写尽可能多的测试,所有的单元测试都是自动进行的,所有的测试都必须始终可以通过。补充阅读一节有TDD更多相关信息的链接。

  虽然其思想非常简单,但是人们发现,在实践中TDD令人难以置信地有效。因为不断增长的单元测试集会对编写的代码提供直接的反馈和验证,所以隐 患不会累积起来而在开发过程的后期引发问题。TDD的另一个优点是,它会产生一个可靠的大型单元测试集,这意味着开发人员可以在离开代码(或者实际上是采 用了另一个开发人员的代码)一段时间后,再返回到代码,并安全地对其进行更改,因为如果在更改中有错误出现,单元测试就会失败。

  要实现有效的TDD过程,开发人员所使用的开发环境需要允许他们针对一个不断变化的代码基址快速编写和执行测试。从EJB开发人员的角度来看, 问题在于,允许EJB在容器中运行的部署过程会极大地减慢编译过程,并使开发环境变得更为复杂。这将会导致下面的危险情况:EJB开发人员不得不“批处 理”他们的测试,并不再经常对代码运行大型单元测试集。虽然仍然进行单元测试,但是这样就降低了TDD方法所引以为傲的快速反馈速度。因此,为了更有效地 支持TDD,我们希望能够消除开发时的EJB部署周期;使用“模仿”EJB容器就是一种实现方法。

  使用TDD开发复杂系统的另一个挑战是,很难将要测试的功能与系统的其他部分隔开。应用程序组件(通常被打包为会话bean)一般要依赖于其他 的组件来向其提供服务。在单元测试环境中,我们希望能消除要测试的组件的依赖性,以便调用的服务返回可预测的测试数据,而不是运行实际的生产代码。对(由 实体bean所表示的)持久性数据的依赖性是这一问题的另一体现。最好可以以一种不依赖于数据库的方式进行单元测试(即使在开发环境中,数据库也通常是共 享资源,因此难以控制)。

  模仿对象(或“mocks”)技术有助于将复杂或难以控制的运行时组件替换为能产生快速单元测试过程的轻量级可控版本。模仿对象的理念是,允许 单元测试用一个专门编写的替代品替换掉正常运行时环境中的部分,替代品实现与正常组件相同的接口,但是更容易为单元测试代码所控制。模仿对象的实现存在于 java.sql JDBC类、java.io IO库、java.net联网库和其它许多标准的Java运行时环境组件中。这些模仿实现使我们可以模拟错误,可以测试数据库代码而无需真的有一个数据 库,测试网络代码而无需有一个真正的服务器(或客户机),等等。总而言之,模仿对象使得对需要复杂运行时环境的代码的单元测试过程更容易处理。 MockEJB是模仿对象领域新近出现的框架,它提供了许多重要的J2EE接口的模仿实现。

MockEJB简介

  MockEJB是Alexander Ananiev所编写的一个EJB测试框架。它结合了许多现有的思想和技术,为EJB开发人员提供了一个强大的测试框架,使他们可以轻松地对EJB进行单 元测试,不管是在EJB容器内部还是外部。实质上,MockEJB提供了EJB所需的所有重要J2EE接口的模仿对象实现,因此为开发人员提供了一个在单 元测试中可以轻松控制的模仿容器实现。它所提供的模仿容器是一个普通Java对象,而且它允许像对普通Java对象那样在J2EE应用服务器的传统容器外 对EJB进行测试。此外,MockEJB也与Cactus服务器端测试框架进行了集成,为需要的EJB开发人员提供了一个应用服务器内的单元测试环境。

  本文重点介绍使用MockEJB在应用服务器外测试bean。对于这种使用方式,MockEJB提供的重要特性包括:

  • 实现接口、调用bean类的EJBObject的自动生成。
  • bean环境的自动配置,包括容器事务、EJBContext对象和EJBMetaData。
  • 一个内存中的JNDI提供程序,它允许绑定和查找容器资源。
  • 对其他EJB操作的调用。
  • 对CMP和BMP实体bean的支持。
  • 一个内存中的JMS提供程序,它允许发送和接收JMS消息。
  • 围绕bean添加拦截器以便允许对测试环境进行控制和监视的能力。

  MockEJB是作为一个Java库提供的,同时提供的还有一些说明其用法的示例和javadoc文档。像大多数库一样,要掌握MockEJB,最容易的方法就是使用它来解决一些简单的问题,所以接下来,我们将看看如何使用MockEJB来测试一些会话bean。

使用MockEJB
  为了说明MockEJB的使用,我们开发了一个非常简单的应用程序,它包含两个会话bean和一个MDB。 本文附带的zip文件包含了一个简单的codeline,其中包含要测试的bean的源代码、单元测试源代码和一个构建和测试bean的Ant build脚本。要构建代码并运行测试,需要安装Ant、Junit和MockEJB,还有JDK。在codeline的README文件中可以找到使用 示例代码的详细说明。

  所提供的EJB是为了研究MockEJB的一些特定功能而开发的,它们非常简单,通过各种服务接口提供了一个基本的计算器。有3个bean:

  • SimpleCalc,最简单的bean,它是一个无状态会话bean,提供了一个为double操作数提供加、减、乘、除服务的接口。该bean会使您了解MockEJB对简单EJB测试的支持。
  • ParsingCalc, 也是一个无状态会话bean,它只提供了一个calculate(字符串表达式)操作。该bean分析传给它的字符串表达式,抽取出所要求的操作的运算符 和操作数,并调用SimpleCalc bean执行计算。该bean会使您了解MockEJB对bean间引用的支持。
  • MessageCalc, 一个消息驱动bean,它通过JMS队列监听消息,抽取任何接收到的文本消息的主体,并使用ParsingCalc bean对其进行分析,将计算的结果返回给请求消息的JMSReplyTo目的站。该bean会使您了解MockEJB对JMS和MDB的支持。

  使用MockEJB测试bean的一般过程如下:

  • 调用MockEJB,以便将其安装为当前环境的默认JNDI提供程序(只需调用静态方法MockContextFactory.setAsInitial())。
  • 创建一个JNDI上下文,并模仿与其关联的EJB容器实例(只需创建InitialContext和MockContainer的实例)。
  • 可选地,创建bean所需的任何模仿J2EE环境对象(例如,JMS工厂和目的站),并将它们安装到JNDI目录下(例如,通过从com.mockejb.jms包创建对象并调用context.rebind(),将它们与模仿JNDI目录下的名称关联)。
  • 为bean创建部署描述符,以便向框架描述它们。MockEJB部署描述符是Java对象而不是XML文档,而且是由适当类(比如SessionBeanDescriptor)的构造对象创建的,构造函数参数定义了接口和要部署的bean实例。
  • 最后,模仿容器的deploy()方法可以对所有的部署描述符对象进行调用,以便部署bean并使它们可以进行测试。

  这个简单的过程一完成,就可以通过您所熟悉的标准J2EE查找/收缩/调用过程来访问bean了。

测试简单EJB
  为了说明这个过程,我们从可能的最简单的例子入手,来了解MockEJB如何让我们在容器外测试简单的独立会话bean。下面的代码片段显示了bean是如何部署到本地内存中的容器中进行测试的:

// Setup the JNDI environment to use the MockEJB 
// context factory
MockContextFactory.setAsInitial();
        
// Create the initial context that will be used for binding EJBs
Context ctx = new InitialContext();
        
// Create an instance of the MockContainer
MockContainer mc = new MockContainer(ctx);

// Create deployment descriptor for our sample bean
// This is used instead of an XML descriptor
SessionBeanDescriptor dd = new SessionBeanDescriptor(
   "java:comp/env/ejb/SimpleCalc", 
   SimpleCalcHome.class, SimpleCalc.class,
   new SimpleCalcBean()) ;
    
// Deploy our bean to the container allowing it to
// be found via JNDI and tested
mc.deploy(dd);

  这段代码设置了使用MockEJB的模仿JNDI实现的环境,而不是基于容器的环境,创建了一个模仿EJB容器来部署bean,然后通过 SessionBeanDescriptor对象来描述bean,将其部署到容器。这种将Java对象作为bean部署描述符的用法,是MockEJB的 容器与真正的应用服务器EJB容器的主要区别。从代码中可以看出,为bean创建描述符非常简单,只需通过指定它要绑定的JNDI名称、提供本地和远程接 口定义的类以及要部署的bean类实例的方式来构造它。

  bean部署到模仿容器上之后,就可以编写针对它的测试了,就像它是部署到常规的应用服务器容器上一样。下面的Junit测试方法显示了调用示例bean的相关方法所需的代码:

public void testTwoPlusTwo() throws Exception
{
    // Look up the home
    Context ctx = new InitialContext();
    Object ejbObj = 
        ctx.lookup("java:comp/env/ejb/SimpleCalc");
    
    // Narrowing is not needed with MockEJB or WebLogic, but 
    // we call it anyway for standardization
    SimpleCalcHome home = (SimpleCalcHome)
       PortableRemoteObject.
          narrow(ejbObj, SimpleCalcHome.class);
    SimpleCalc calc = home.create();
    assertEquals("Add operator failure", 4.0, 
                  calc.add(2.0, 2.0), 0.0) ;
}

  可以看出,如果在一个应用服务器容器中运行,该代码就与调用bean操作所需的代码相同,所以一旦测试bean已经部署,就不需要特定于 MockEJB的编程了。在本文附带的示例代码中,TestSimpleCalcBean Junit测试用例类包含了测试SimpleCalc bean的例子代码。但是,要注意,执行特定于MockEJB的容器初始化和bean部署的代码已经从Junit测试用例类被重构为一个称为 MockBeanTestBase的抽象基类。该类可以提供其他的特性(比如,在EJB容器内运行),并可避免测试之间的代码重复。

测试引用其他EJB的EJB
  前面的例子明显过于简单了,因为bean本身没有使用驻留在容器内的资源,所以我们只需实例化bean类的对象并调用其方法也能达到相同的效果。我们 来看看MockEJB如何帮助我们测试引用其他bean的会话bean。在我们的例子代码中有一个ParsingCalc bean,它需要SimpleCalc bean的服务来执行计算。

  通过将所需的所有bean部署到模仿容器上,并关联正确的JNDI名称,MockEJB使EJB相互之间可以轻松地进行查找和引用。对应的示例代码可在TestParsingCalcBean Junit类中找到。初始化的关键部分显示在下面的代码片段中:

// Initialize initial context and container here
// ...
        
// Create deployment descriptor for the bean under
// test.
SessionBeanDescriptor testDD = 
   new SessionBeanDescriptor(
      "java:comp/env/ejb/ParsingCalc", 
      ParsingCalcHome.class, ParsingCalc.class,
      new ParsingCalcBean()) ;
// Create deployment descriptor for the bean that 
// the bean under test relies upon.
SessionBeanDescriptor depDD = 
   new SessionBeanDescriptor(
      "java:comp/env/ejb/SimpleCalc", 
      SimpleCalcHome.class, SimpleCalc.class,
      new SimpleCalcBean()) ;
// Deploy both beans to the mock container
mc.deploy(depDD) ;
mc.deploy(testDD);

  (注意,在所提供的示例代码中,bean部署实际上是使用来自Junit测试类扩展后的抽象基类的deployRemoteSessionBean()方法实现的。在上面的代码片段中我们将所需的过程展示得非常清楚。)

  现在,两个bean都部署到模仿容器上了,而且如果SimpleCalc所绑定的JNDI名称(在上面的例子中是java: comp/env/ejb/SimpleCalc)与ParsingCalc bean在其初始上下文中所查找的名称匹配,MockEJB就会返回一个到正确的EJB对象的引用。在例子单元测试类的 testParsingCalcOperations方法中,可以找到一些ParsingCalc bean的示例单元测试代码,其中bean是使用常规的EJB调用进行测试的。如果运行测试,ParsingCalc bean就会成功定位并调用对SimpleCalc bean的操作。

  这个例子说明了MockEJB的最简单的用途,但是MockEJB还提供了一个非常有用的功能,即,在容器外开发、测试和调试会话bean的能力。同样,我们也不打算利用EJB容器所提供的任何更为复杂的功能。

测试MDB
   现在我们来考虑如何利用MockEJB的JMS功能在容器外测试MDB。显然,测试MDB与测试会话bean(或实体bean)截然不同,因为bean只 能通过向其正在监听的适当JMS主题或队列发送消息而使用。因此,虽然仍然需要部署bean本身,但是设置MDB以进行测试的大部分工作都与创建JMS对 象并将bean连接到正确的目的站有关。幸运的是,MockEJB使得在短短几行代码中实现所有这些任务成为可能。下面的代码片段说明了如何设置环境以便 测试MDB:

// Initialize initial context and container
MockContextFactory.setAsInitial();
Context ctx = new InitialContext();
MockContainer mc = new MockContainer(ctx);

String factoryName = "jms/QueueConnectionFactory" ;
String requestQueueName  = "jms/queue/CalcRequestQueue" ;
String responseQueueName = "jms/queue/CalcResponseQueue" ;

// Create the mock JMS objects and bind them to
// the appropriate names in the mock JNDI directory
QueueConnectionFactory qcf =
   new QueueConnectionFactoryImpl() ;
ctx.rebind(factoryName, qcf);
Queue queue = new MockQueue(requestQueueName) ;
ctx.rebind(requestQueueName, this.queue);
        
ctx.rebind(responseQueueName, 
   new MockQueue(responseQueueName));
 // Create an instance of the bean under test and
// attach it to the test queue as a listener
MessageCalcBean beanObj = new MessageCalcBean() ;       
((MockQueue)queue).addMessageListener(beanObj) ;

// Create a deployment descriptor for the MDB
// and set the flag indicating that the JMS
// objects are already created and bound to the
// specified names
MDBDescriptor mdbDD = new MDBDescriptor(
   factoryName, requestQueueName, beanObj) ;
mdbDD.setIsAlreadyBound(true) ;

// Deploy the MDB ready for testing
this.container.deploy(mdbDD);

  从代码片段中可以看出,设置bean的大部分代码都牵涉到创建适当的JMS模仿对象并将其绑定到模仿JNDI目录中所要求的名称。现在,当 MDB查找队列连接工厂时,就会被传递一个到上面所创建的模仿工厂的引用;类似地,当它请求CalcRequestQueue时,就会被传递一个到模仿队 列的引用,允许我们在需要时操纵和监视队列。对应于此过程的例子代码可在MockBeanTestBase类的 deployQueueMessageDrivenBean()方法中找到。

  现在我们可以通过创建适当的(模仿)JMS消息来发送它,并通过模仿队列将其分派给bean,来对MDB进行测试。相应的代码片段如下:

// ... following from previous code fragment
    
// Provide us with access to the queues
QueueConnection conn = qcf.createQueueConnection();
QueueSession sess = conn.createQueueSession( false, 
                           Session.AUTO_ACKNOWLEDGE);
 // Create our test message
TextMessage reqMsg = session.createTextMessage();
    
// Look up the reply queue and set in the message
Queue replyQ = (Queue)ctx.lookup(RESPONSE_QUEUE_NAME) ;
reqMsg.setJMSReplyTo(replyQ) ;
    
// Start the connection and create a receiver to 
// to begin receiving messages
conn.start();
QueueReceiver recv = sess.createReceiver(replyQ) ;
 // Get rid of any messages that might be on the 
// response queue because of failed tests
while(recv.receiveNoWait()!=null) ;
    
// Send a message to run a unit test
reqMsg.setText("2.0 + 2.0") ;
sender.send(reqMsg);
TextMessage reply1 = 
  (TextMessage)recv.receive(RECEIVE_TIMEOUT_SEC) ;
assertNotNull(reply1);
assertEquals("Wrong addition result", 
    "2.0 + 2.0 = 4.0", reply1.getText()) ;

  在测试代码中,我们可以使用标准的JMS API来查找队列和连接工厂,并创建、发送和接收消息。因为我们使用了模仿队列实现,MockEJB的JMS实现会处理我们发送给请求队列的消息,调用 MDB的onMessage()方法。这会阻塞直到onMessage()方法返回,所以我们可以立即检查响应。MockEJB的JMS实现的阻塞(同 步)特性非常有利于单元测试,因为它允许我们测试JMS驱动的操作的结果,而无需处理单元测试代码中无法预测的延迟和超时。它还允许我们对会话bean和 MDB连接在一起的地方进行集成测试。

  除了标准的JMS API的实现外,MockEJB还提供了各种方便的方法来发送消息并检查队列的内容,而无需求助于有时会很麻烦的JMS API。在本例中,我们没有使用这些方法,因为这种方法有一个缺点,即,当在一个真正的EJB容器内运行EJB时,测试不能重用,而本文所提供的示例代码 则在两种模式下都可以运行单元测试。

  总结一下,在几段短小的代码片断中,我们使用MockEJB将会话bean和MDB部署到一个本地内存中的容器,将bean绑定到JNDI目 录,以便允许它们互相调用,并使用MockEJB的内存中的JMS提供程序测试了一个MDB,而无需在容器中配置真正的JMS提供程序。遗憾的是,在这篇 短小的文章内,无法再展示更多的MockEJB特性,但是我们希望您已经看到了该框架支持有效的测试驱动EJB开发的潜力。

MockEJB的其他特性
  虽然不能演示MockEJB的所有特性,但是还是可以简要地探讨一下这个功能丰富的框架的其他还未讨论的特性。 测试实体bean

  除了提供许多测试会话bean和消息驱动bean的方便功能外,MockEJB也为在容器外测试BMP和CMP实体bean提供了许多方便功 能。模仿容器提供了一个内存中的实体bean数据库,允许用测试数据来填充它以提供没有数据库的可预测测试。对BMP实体bean的处理方式类似于会话 bean,因为出现了bean实现,虽然该实现是在运行时为CMP实体bean生成的。MockEJB还提供了自己的方面实现(此处是AOP术语),允许 安装方面以便提供特定的finder和容器管理关系(Container-Managed Relationship,CMR)行为。

使用MockRunner的事务和JDBC
  如果需要测试交叉bean的事务性行为,MockEJB可以与MockRunner的J2EE UserTransaction接口的MockUserTransaction实现一起使用。模仿用户事务的实例可以绑定到MockEJB的模仿JNDI 目录的javax.transaction.UserTransaction名称下,然后就可以操纵和监视该事务对象以检查行为的正确性。类似地, MockRunner的JDBC实现可在MockEJB内使用,以便提供一个模仿数据源,该数据源提供标准的测试数据,而且要测试的代码可以监视其使用的 正确性。

AOP和拦截器
   如上所述,MockEJB提供了一个简单的AOP框架,它允许我们在EJB处理生命周期中的任何点插入代码。MockEJB中的 方面 被定义为 拦截器 切入点 的 组合,其中拦截器指定将会在调用目标方法之前以及之后运行的逻辑(即AOP术语中的“环绕通知”),而切入点定义要截取的方法的集合。所提供的实现非常强 大且灵活,允许在框架(或者bean或测试代码)中的任何方法调用时引入拦截器,允许监视测试(如:检查方法是否被调用)或插入数据(如:从BMP finder方法返回一个主键列表)。

  实际上,AOP为模仿对象方法提供了一种强大的可选方案,因为拦截器允许您改变目标类的单个方法的行为,而不是必须将整个类作为一个模仿对象 重新实现。对于MockEJB,这两种方法可以互换。例如,您可以创建整个会话bean的模仿版本(例如,使用EasyMock框架),或者只截取并更改 bean中选定的方法。

在容器中使用MockEJB
  最后,有一个MockEJB的特性我们曾提到过,但没有详细介绍,就是在常规的EJB容器内使用的能力。MockEJB的这种用法可以为bean提供 一个容易控制的运行时包装器,因此允许模拟在常规的单元测试中难以创建的条件,从而使在容器内进行的EJB单元测试更为简单。

  虽然在容器外运行EJB允许您使用TDD方法开发代码,但是它并不能完全取代容器内测试。MockEJB不支持基于XML的部署描述符(更不 用说特定于供应商的描述符和配置文件了),所以将EJB部署到容器中并运行单元测试是验证其正确性的重要组成部分。使用MockEJB时,开发人员大部分 的开发工作都可以依赖于容器外模式,运行容器内测试就不那么频繁了——例如,在向版本控制系统提交更改之前。

  为了实现容器内支持,MockEJB提供了一个对Cactus ServletTestCase类的扩展,称为OptionalCactusTestCase,它允许在服务器端的Cactus下或者使用MockEJB 的容器在服务器外运行测试用例子类中的测试。如果要在服务器的Cactus下运行测试,则通过将系统属性mockejb.cactus.mode设置为 true来控制类的行为。在运行时,如果需要的话,测试可以调用isRunningOnServer()方法在两种模式之间改变行为。容器内模式可以灵活 地将容器和模仿所提供的资源进行混合和匹配。这是由MockEJB的JNDI上下文完成的,需要时也可以委托给容器的上下文。因此,可以依赖模仿EJB来 控制测试的边界,而其他资源(比如JMS和数据源)可以由容器来提供,以便使测试更为逼真。

  本文附带的示例代码允许在EJB容器内或容器外对bean运行所提供的单元测试,因此可以视为在容器内使用MockEJB的例子。


结束语
  在本文中,我们揭示了一些在TDD方法的快速开发/测试/重构周期中进行EJB测试所产生的问题,并引入了一种测试框架,MockEJB。通过提供一个支持内存中EJB测试的轻量级模仿EJB容器,该框架可以帮助解决这些问题。

  我们看到,借助于比较少的代码(其中大部分都可以放在可重用的基类中),就可以将会话bean或MDB部署到模仿容器中,并在本地对其进行测试,而无需配置和使用完全的J2EE应用服务器。

  此外,MockEJB还提供了其它许多有用的功能,包括测试实体bean的能力,对一旦完成初始开发就可以在容器内运行的支持(提供对bean 的运行时环境的方便控制),对JDBC和J2EE事务的支持(通过Mock Runner),以及一个灵活而强大的基于方面的拦截器实现,它允许对测试环境进行控制和监视。

  我们鼓励您在项目中使用MockEJB,体验它所提供的流线化的单元测试过程,尤其是您打算对EJB组件使用测试驱动开发时。

----------------------------------------------------------------------------------------------------------


以后写ejb,谁再以ejb单元测试不好写为理由不写单元测试,就弄死谁……哈哈。



评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值