SOA环境中的测试驱动的开发,第1部分:测试数据映射

日期: 2009-06-04 作者:Donald Vines 来源:TechTarget中国 英文

  本文向您介绍用于SOA环境的测试驱动的开发理论。本文将向您说明如何为SDO数据映射编写测试用例,并在发布这些数据映射以供其他SCA模块使用之前,提供用于编写测试用例和使用Junit、Cactus及IBM WebSphere Integration Developer执行这些用例的逐步说明。

  来自IBM WebSphere Developer Technical Journal.

  引言

  在软件工程方面,两个最近的重大变化是对测试驱动的开发和持续集成的使用日益增加。作为转向敏捷软件开发方法的一部分,这些实践已在基于Java的传统应用程序开发中使用了许多年,最近开始用于SOA解决方案的开发。

  为此,一篇最近的developerWorks文章描述了IBM WebSphere Integration Developer V6.1的一个新功能,该功能使您能够创建测试用例,并且只需单击一个按钮即可在无人参与的情况下运行它们。另一个文章系列阐述了如何使用JUnit和Cactus来测试服务组件体系结构(Service Component Architecture,SCA)组件、BPEL组件和人工任务。这些文章对在SOA环境中工作的所有Java开发人员都非常有帮助。为了补充那些资源,这个由两部分组成的文章系列将研究两个同等重要的附加主题:

  ·数据映射的单元测试在SOA项目的早期阶段中极其有用。测试数据映射对于不成熟的服务接口(其中数据要么还没有很好地建立,要么不稳定)来说是必需的,并且对于较成熟的服务接口也非常有用。这些测试将使您能够不必太关心重构数据类型。您可以做出一些更改,重新测试映射,然后重新测试使用这些映射的模块。

  ·持续集成是每天运行多次的完全自动化和可再现的构建(包括测试),是用于传统应用程序并得到广泛认可的开发实践。要对SOA环境应用这种敏捷开发实践,您需要能够作为定期计划的集成构建的一部分执行单元测试。这是在诸如WebSphere Integration Developer等集成开发环境(IDE)之外进行的,因此一般需要通过Ant运行单元测试。

  本文向您说明如何独立于使用数据映射的SCA模块对数据映射进行测试。通过使您能够在发布库以供模块使用之前对库进行测试,数据映射测试对在共享库中定义公共数据类型和数据映射的标准实践形成了补充。您甚至可以在创建任何模块之前对库进行测试。这与测试驱动的开发实践是一致的。

  第二部分将介绍如何在SOA环境中使用持续集成,使用诸如Ant等自动化构建工具来运行单元测试,生成测试报告,并在测试失败的情况下向开发人员发送电子邮件。

  对数据映射进行单元测试

  为了了解如何测试数据映射,请考虑以下场景:

  ·您有一个地址清理服务,它检查地址的有效性,但是需要给出一个地址作为被逗号分隔的值;也就是说,库中存在一种AddressCSV数据类型。

  ·该SOA解决方案的其他部分要求地址使用单独的字段来表示地址元素,例如company、addressLine1等等;也就是说,库中存在一种Address数据类型。

  ·该库具有两个数据映射,其中一个从Address映射到AddressCSV(图1),另一个从AddressCSV映射到Address(图2)。

            

  图1. Address_To_AddressCSV数据映射

               
 
  图2. AddressCSV_To_Address数据映射
 
  可以看出,上述映射相当简单,逐个字段的映射是相对简单的。然而,对于大型业务对象,映射可能相当复杂,辨别属性彼此间的映射通常变得非常困难。创建数据映射可能是非常繁琐且很容易出错的任务,从而突出了重复测试的重要性。

  要测试上述数据映射,您通常要编写两个JUnit测试用例。对于此示例场景,为您提供了代码示例以供下载。该示例代码在一个项目交换文件中,您可以将该文件导入WebSphere Integration Developer V6.1工作区。导入以后,打开Business Integration透视图查看三个示例项目:

  ·L_AddressCleansingService:此库具有用于组合应用程序的数据类型和数据映射,并将由构成SOA解决方案的模块重用。
  ·T_AddressCleansingService:此模块用于测试数据映射,并将仅部署到测试环境中的IBM WebSphere Process Server。它不是SOA解决方案的一部分。
  ·T_AddressCleansingServiceJUnitWeb:此动态Web项目包含了将在WebSphere Process Server容器中执行的Junit测试用例。它是T_AddressCleansingService测试模块的一部分。

  此场景假设该库的数据类型和映射已经存在,因此本文将不介绍如何创建它们。您可以查看该库以了解它们的定义。有关如何创建数据映射的信息,您还可以查看这个WebSphere Integration Developer指导教程。

  本文的其余内容将研究用于测试数据映射的三个大致步骤:

  ·创建测试模块和Web项目
  ·创建测试用例和数据映射
  ·运行测试用例

  下面几个部分将详细描述这些步骤。

  1. 创建测试模块和Web项目

  对于此步骤,您可以选择按照以下说明操作或下载并导入项目交换文件,以便能够使用所提供的测试模块和Web项目。如果您选择后者,请向前跳到步骤2。

  要创建测试模块,请执行以下步骤:

  ·在WebSphere Integration Developer的Business Integration透视图中,打开Business Integration视图。请单击右键,然后选择New => Module。在New Module对话框中,输入名称T_AddressCleansingService,然后单击Finish。

  ·要创建动态Web项目,请切换到J2EE透视图。右键单击T_AddressCleansingServiceApp并选择New =>Dynamic Web Project。在New Dynamic Web Project对话框中,输入T_AddressCleansingServiceJUnitWeb并单击Finish。

  ·下一步,创建测试模块与包含有要映射的数据类型和要测试的数据映射的库之间的关联。为此,请切换到Business Integration透视图。选择T_AddressCleansingService并双击打开Dependency编辑器。展开Libraries并使用Add功能添加L_AddresCleansingService。

  ·接下来,您需要将Log4J、Junit和Cactus框架添加到测试模块。为此,将以下库添加到T_AddressCleansingServiceJUnitWeb项目的web-inflib文件夹:

  从Log4J分发包下载:
  ·log4j-1.2.14.jar

  从JUnit分发包下载:
  ·junit-3.8.1.jar

  从Cactus分发包下载:
  ·aspectjrt-1.2.1.jar
  ·cactus-1.7.1.jar
  ·commons-httpclient-2.0.2.jar
  ·commons-logging-1.0.4.jar

  最后,您需要将Cactus Servlet定义添加到Web应用程序中的web.xml文件。为此,请剪切清单1中的代码,并将其直接粘贴到动态Web应用程序部署描述符中的现有描述和欢迎文件之间:
 
  清单1
      
  <display-name>T_AddressCleansingServiceJUnitWeb</display-name>

        <servlet>
                <servlet-name>ServletRedirector</servlet-name>
                <servlet-class>
                       org.apache.cactus.server.ServletTestRedirector
                </servlet-class>
                <init-param>
            <param-name>param1</param-name>
             <param-value>value1 used for testing</param-value>
    </init-param>
        </servlet>

        <servlet>
                <servlet-name>ServletTestRunner</servlet-name>
                <servlet-class>
                        org.apache.cactus.server.runner.ServletTestRunner
                </servlet-class>
        </servlet>
 
        <servlet-maping>
     <servlet-name>ServletRedirector</servlet-name>
     <url-pattern>/ServletRedirector</url-pattern>
        </servlet-maping>
 
        <servlet-maping>
     <servlet-name>ServletTestRunner</servlet-name>
     <url-pattern>/ServletTestRunner</url-pattern>
        </servlet-maping>

        <welcome file list>

  2. 创建测试用例和数据映射

  下一步,您将为Address_To_AddressCSV数据映射编写测试用例。您的测试用例将填充一个输入的Address对象,调用该映射以产生输出AddressCSV对象,然后将最终获得的AddressCSV对象与预期的结果做比较。如果它们相等,则认为测试成功;如果它们不相等,则测试失败。(所包括的项目交换文件还包含一个用于AddressCSV_To_Address映射的单元测试用例。)

  创建单元测试涉及到以下步骤:

  ·创建测试用例

  典型的JUnit编程模型通过扩展JUnit提供的TestCase类创建测试类。Cactus框架是JUnit的扩展,Junit使您能够在一个容器中运行单元测试。由于您是在使用Cactus框架,您将扩展Cactus测试类org.apache.cactus.ServletTestCase。为此,请执行以下操作:

  ·转到Web透视图中的Project Explorer视图,展开Dynamic Web Projects => T_AddressCleansingServiceJUnitWeb => Java Resources => JavaSource。
  ·右键单击Java Source,并选择New => Package以创建适当的包。右键单击该包,选择New => Class以创建类,并输入如下代码:

  清单2
        
  package com.ibm.issw.service.addresscleansing.test;

  import org.apache.cactus.ServletTestCase;

  public class AddressCleansingServiceTest extends ServletTestCase {

  ·编写setup()和teardown()方法

  JUnit框架为您提供了相关方法,您可以实现这些方法来为测试用例设置环境,并在运行测试用例以后销毁该环境。其中的事件序列如下:调用setUp(),调用testxxx()方法,调用tearDown()。该测试类中的每个testXXX()方法都将发生此事件序列。清单3显示了示例setUp()和tearDown()方法。

  清单3
      
private DataObject expectedAddress;
private String expectedWholeAddress;
private DataObject expectedAddressCSV;
private MapService mService;

private static Logger logger = Logger.getLogger(
    AddressCleansingServiceTest.class );

protected void setUp() throws Exception {
    expectedAddress = createAddress(
        “IBM Corporation”,”1133 Westchester Avenue”,
        “”,”White Plains”,”NY”,”10604″);
    expectedWholeAddress = createWholeAddress(
        “IBM Corporation”,”1133 Westchester Avenue”,
        “”,”White Plains”,”NY”,”10604″);
    expectedAddressCSV = createAddressCSV(expectedWholeAddress);
  
    // Get the map service so we can invoke the mapping operation.
    mService = (MapService) ServiceManager.INSTANCE.locateService(
        “com/ibm/wbiserver/map/MapService”);
}

protected void tearDown() throws Exception {
    expectedAddress = null;
    expectedAddressCSV = null;
    expectedWholeAddress = null;
    mService = null;
    }

  清单3显示了以下内容:

  ·由测试方法共享的私有数据成员的定义。这些数据成员将在setUp()中初始化,在testXX()中使用,并在tearDown()中销毁。
  ·日志记录服务的创建,以便您能够在测试方法中记录日志。
  ·“实际”输入SDO的创建和初始化,以便您能够通过createAddress()方法将其传递给该映射。这只是创建了一个Address SDO并将其初始化为给定的值。
  ·“预期的”输出SDO的创建和初始化,以便您能够将其与该映射返回的实际输出做比较。这是通过createWholeAddress()和createAddressCSV()方法完成的。

  创建测试方法

  JUnit命名约定规定所有测试方法名称都应以单词“test”开头。这些方法不带任何参数,是空方法。测试失败通过引发未经检查的异常来指示,通常是使用JUnit提供的断言和故障方法。测试成功通过测试方法的完成来指示。此示例的测试方法类似于清单4。

  清单4
      
  public void testAddress_To_AddressCSVMap()
throws WBIMapNotFoundException, WBIMapFailureException, WBIMapServiceException {
   try {
 logger.debug(“Invoking Address_To_AddressCSV map.”);

 BOFactory bof = (BOFactory)ServiceManager.INSTANCE.locateService(
         “com/ibm/websphere/bo/BOFactory”);
 DataObject actualAddressCSV = bof.create(
         “http://L_AddressCleansingService”, “AddressCSV”);

 HashMap inputMap = new HashMap();
 HashMap outputMap = new HashMap();
 inputMap.put(“Address”, expectedAddress);
 outputMap.put(“AddressCSV”, actualAddressCSV);
 mService.transform(“http://L_AddressCleansingService”,
         “Address_To_AddressCSV”, inputMap, outputMap, (ExecutionContext)null);
      assertEquals(actualAddressCSV.getString(“wholeAddress”),
         expectedAddressCSV.getString(“wholeAddress”));
   } catch (WBIMapNotFoundException e) {
      logger.debug(“WBIMapNotFoundException: ” + e.getMessage());
 throw e;
   } catch (WBIMapFailureException e) {
 logger.debug(“WBIMapFailureException: ” + e.getMessage());
 throw e;
   } catch (WBIMapServiceException e) {
 logger.debug(“WBIMapServiceException: ” + e.getMessage());
 throw e;
   }
}

  清单4显示了以下内容:

  ·使用Log4J在测试过程中显示某些消息。请注意,Log4J.properties文件需要在类路径上,以指定要使用的搜索路径,这里是通过向应用程序服务器的类路径添加文件夹来实现的。为此,请执行以下步骤:

  ·打开管理控制台。
  ·导航到Application servers => server1 => Process Definition => Java Virtual Machine。
  ·将您放置log4j.properties文件的文件夹添加到类路径,如清单5所示。

  清单5
        
log4j.rootLogger=WARN, RootAppender, ConsoleAppender

log4j.appender.ConsoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.ConsoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.ConsoleAppender.layout.ConversionPattern=[%d] %-5p %c{2} – %m%n

log4j.logger.com.ibm.issw=DEBUG

  ·使用transform()方法调用数据映射。此示例中使用了通用的transform()方法,它可以调用将一个或多个SDO转换为另一个SDO的映射,但是您也可以使用simpleTransform()方法调用数据映射,因为此方法从一个SDO转换为另一个SDO。清单6中的代码片段显示了如何使用simpleTransform()。

  清单6
        
mService.simpleTransform(
   ” http://L_AddressCleansingService”,
   “Address_To_AddressCSV”
   input,
   output);

  ·有关该操作返回的数据的一连串断言;特别是,您将考虑映射的定义并包括有关每个转换的断言。为此,您将使用输入和输出数据对象上的get方法,并使用JUnit assertEquals()。

  有了此代码后,您就做好了运行测试的准备。

  3. 运行测试用例

  要运行测试,请执行以下操作:

  首先,将测试模块添加到服务器,并确保服务器已启动。

  在Business Integration透视图中,转到Servers视图。右键单击服务器,选择Add Remove Projects,并将T_AddressCleansingServiceApp添加到服务器。您现在已经拥有了可用于执行的测试类。

  要执行测试类,请转到J2EE透视图中的Project Explorer视图。选择AddressCleansingServiceTest类,然后从Run菜单中选择Run…。

  在Run对话框中,从可能的Configurations列表中选择JUnit,然后单击New。

  选择Arguments窗格。在VM参数下,输入-D参数,如清单7所示。(此参数指定本地主机和端口9083;如果您的服务器或用于HTTP请求的端口与此不同,请根据需要调整此字符串以匹配您的值。)

-Dcactus.contextURL=http://localhost:9083/T_AddressCleansingServiceJUnitWeb
 
  选择Run来启动测试。JUnit视图然后显示运行测试的结果(图3)。

         

  图3. 执行测试的结果
 
  现在您已经建立了这个启动配置,您只需选择它并单击Run => JUnit Test即可重复运行该类。

  总结

  本文演示了如何为数据映射编写测试用例,以及如何使用JUnit和Cactus在WebSphere Process Server容器中运行它们。这使您能够在实现使用SDO数据类型和数据映射的业务流程(SCA模块)之前,首先为SDO数据类型和数据映射编写测试用例。这些测试的可用性提供了有关数据映射的快速反馈,并支持SOA解决方案中随后可能需要的数据类型重构。在第2部分中,您将看到如何在持续集成服务器中运行这些单元测试用例。

  关于作者

  Donald Vines是IBM的一名执行IT架构师,他负责北美范围的WebSphere迁移实践。他目前从事的工作是为IBM主要客户创建解决方案体系结构,并在开发SOA和企业现代化项目过程中指导设计师和软件开发人员。他曾是对象管理组织(Object Management Group, OMG)的一位技术代表,在该组织中和其他人一同创立在Internet中广泛使用的Internet Inter-ORB Protocol(IIOP)。Don还是Sun认证的企业架构师、Sun认证的Java程序员和OMG认证的UML2专业人员。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐

  • 案例管理如何强化SOA环境

    保持SOA环境平滑运行牵涉到大量移动部件的管理:API、微服务、移动性以及日益火爆的物联网。在这基础上,还会涉及安全、隐私、监管合规性等问题。

  • 内隐服务契约比服务接口更重要

    4月21日,亚马逊Web服务宕机数小时,立刻导致很多Web站点和公司“爆炸”。亚马逊Web服务作为“全球最大、最安全和最值得信任的Web服务”之一而久负盛名。

  • 企业级软件开发需要什么样的框架?

    分析领域特定的问题。比如赶集网这一分类信息网站,她的定位是解决都市人寻求房屋出租、二手房、二手车、二手物品交易、求职招聘等生活信息的需求的。

  • SOA安全:安全令牌和SAML

    SOA环境下的安全一定首先要处理好访问控制的问题,必须经得起“千锤百炼”的考验。下面我们就来看看保证Web服务安全的常见安全令牌解决方案。