使用 soapUI 对异步 BPEL 流程进行单元测试

作者:Daniel Amadei

2012 年 2 月

凭借对模拟和 WS-Addressing 的支持,soapUI 可以用于测试异步 BPEL 流程。

下载
download-icon13-1
Oracle SOA Suite
download-icon13-1Oracle JDeveloper
download-icon13-1Oracle BPEL Process Manager

SoapUI 是测试 SOA 应用程序的有效工具。您可能已经在使用它测试同步服务,甚至已经通过它实现了这些测试的自动化。但您是否知道还可以使用 soapUI 测试异步 BPEL 流程?这可能要归功于 soapUI 对模拟和 WS-Addressing 的支持。本文将介绍如何实现这种测试。

了解如何公开 BPEL 流程以及 WS-Addressing 的作用

默认情况下,BPEL 流程将作为 SOAP over HTTP Web 服务提供。因此,这些流程可以像任何其他 Web 服务一样通过 soapUI 轻松进行测试。当 BPEL 流程是同步流程时,这很容易实现:soapUI 将发出一个请求,并验证收到的响应。所有这些均发生在同一 HTTP 连接上。

但如果您希望异步流程的单元测试实现自动化,该怎么办呢?SoapUI 对这种(不是那么简单)任务很有帮助。

值得注意的是,对于异步流程,响应实际上是作为被调用的流程对其调用方的回调来发送的。这使得调用方能够接收回调的请求。调用方必须提供被调用流程希望的接口,这样才能发送响应。SoapUI 具有此功能,可以充当服务器来接收回调。

所有这些均依赖于 soapUI 和 Oracle SOA Suite 这两种工具对 WS-Addressing 的支持。

了解 WS-Addressing

Wikipedia 对 WS-Addressing(Web 服务寻址)的定义如下:

一种允许 Web 服务传送寻址信息的、与传输方式无关的机制的规范。它主要由两部分组成:一种用于传送对 Web 服务端点引用的结构,以及一组将寻址信息与特定消息相关联的消息寻址属性。

WS-Addressing 在 Oracle BPEL Process Manager 的异步流程架构中起到非常重要的作用。调用异步 BPEL 流程时,可以使用 WS-Addressing 标头指定回调信息。当 BPEL 必须回调以发送异步响应时,它将检查这些标头并使用指定值发送响应。当一个 BPEL 流程调用另一个异步流程时,它将自动设置标头。

通过这篇文章,您将看到 soapUI 如何通过 WS-Addressing 调用流程并接收异步回调。

测试案例

本文中用于模拟异步场景的应用程序是一个非常简单的异步 BPEL 流程。它复制所收到的字符串并将其作为回调响应发送给请求方。该场景使用 soapUI 发送请求,等待回调,然后查找发送和接收值之间的匹配。

测试的第一步是在 JDeveloper 中创建一个新应用程序。此测试使用 11.1.1.5 版的 Oracle JDeveloper 和 Oracle SOA Suite 作为示例,但也可以使用这两个产品的任何 11g 版本。

使用 JDeveloper,创建一个新的 SOA 应用程序并将其命名为 OTNTestingAsyncBPEL,如图 1 所示。


bpel-amadei-fig01
图 1 — 创建应用程序

在这个应用程序内,创建一个新项目(在下一屏幕中您应被重定向到项目创建):

  1. 将其命名为 AsyncBPELTesting
  2. 单击 Next 并选择 Composite With BPEL Process
  3. 单击 Finish

bpel-amadei-fig02
图 2 — 创建 SOA 项目

系统将提示您创建 BPEL 流程。将其命名为 AsyncBPELProcess 并确保其模板为“Asynchronous BPEL Process”,以便使用异步结构创建该流程,这正是本场景所要求的。

bpel-amadei-fig03
图 3 — 创建 BPEL 流程

您的 BPEL 流程应与图 4 中的相同。这是一个典型的异步流程,以单向方式接收请求。正如该架构所决定的,客户端不会立即收到响应;相反,客户端稍后受到被调用流程的激发,通过所谓“回调”(但实际上是由被调用流程向调用方发送一个请求)接收响应。


bpel-amadei-fig04
图 4 — 所创建的异步 BPEL 流程

我们的 BPEL 流程将非常简单:将作为输入接收到的文本复制到输出。该接收值将在稍后用于测试(使用 soapUI)是否收到对指定请求的正确响应。在 BPEL 流程中实现此逻辑:


  1. 创建一个 Assign 步骤并将其命名为 copyRequestValueToResponse
  2. 编辑 Assign 并将 process/input 元素收到的值(在 inputVariable 的有效负载内)复制到输出变量的 processResponse/result 元素,如图 5 所示。outputVariable 将在由 callbackClient 步骤使用时发送到客户端。

bpel-amadei-fig05
图 5 — 将请求数据复制到回调响应

现在可以部署该项目,并可运行初步测试。现在暂时不管回调。

在 SOAP UI 中创建测试项目

创建的第一个测试只是启动流程。在 soapUI 中,通过按 Ctrl+N 创建一个新的测试项目。

输入 http://localhost:7001/soa-infra/services/default/AsyncBPELProject/asyncbpelprocess_client_ep?WSDL 作为 WSDL 的 URL,并将项目命名为 AsyncBPELProjectTest,如图 6 所示。将创建该项目并会有两个绑定可用,一个用于请求,另一个用于回调。


bpel-amadei-fig06
图 6 — 创建 SOAP UI 项目

展开 AsyncBPELProcessBinding 流程并打开“Request 1”项。将 input 标记的内容更改为“First test...”,如下所示。


<soapenv:Envelope 
   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
   xmlns:asy="http://xmlns.oracle.com/OTNTestingAsyncBPEL/AsyncBPELProject/AsyncBPELProcess">
   <soapenv:Header/>
   <soapenv:Body>
      <asy:process>
         <asy:input>First test...</asy:input>
      </asy:process>
   </soapenv:Body>
</soapenv:Envelope>

提交请求。您应该不会收到任何响应内容。单击 soapUI 中的“http log”选项卡后,收到的返回代码应是 202。根据 HTTP 协议语义,该返回代码表示请求已接受。下例描述了您可能在 soapUI 中看到的日志记录:


Sun Nov 13 09:30:38 BRST 2011:DEBUG:<< "HTTP/1.1 202 Accepted[\r][\n]" 
Sun Nov 13 09:30:38 BRST 2011:DEBUG:<< "Date: Sun, 13 Nov 2011 11:30:38 GMT[\r][\n]" 
Sun Nov 13 09:30:38 BRST 2011:DEBUG:<< "Content-Length: 0[\r][\n]" 
Sun Nov 13 09:30:38 BRST 2011:DEBUG:<< "Content-Type: [\r][\n]" 
Sun Nov 13 09:30:38 BRST 2011:DEBUG:<< "X-ORACLE-DMS-ECID:
 1b7e5955c26b51de:5a1f5e8a:1339c9c6d49:-8000-000000000000076b[\r][\n]" 
Sun Nov 13 09:30:38 BRST 2011:DEBUG:<< "X-Powered-By: Servlet/2.5 JSP/2.1[\r][\n]" 
Sun Nov 13 09:30:38 BRST 2011:DEBUG:<< "[\r][\n]"

使用 Oracle Fusion Middleware (FMW) Control 检查创建的实例,可以看到 BPEL 流程所发生的情况。在 SOA Server 的 http://<ip>:<port>/em 处访问服务器上的 FMW Control。例如,在典型安装中默认主机和端口将是:http://localhost:7001/em

在 FMW Control 中,找到项目 AsyncBPELProject 并单击 Instances 选项卡。将显示您的实例,如图 7 所示。


bpel-amadei-fig07
图 7 — 第一个测试中创建的实例

单击该实例可显示它已执行的所有步骤,如图 8 所示。


bpel-amadei-fig08
图 8 — 该实例执行的所有步骤

通过单击 BPEL 流程实例,您应该能够在新的浏览器窗口中看到 BPEL 流。展开 callbackClient 步骤中的 payload 元素,您应看到我们在 processResponse/result 元素中发送的值,如图 9 所示。


bpel-amadei-fig09
图 9 — BPEL 流

由于未指定任何回调信息,回调被忽略。

现在看看 soapUI 如何通过充当一台能够接收异步回调的服务器来帮助测试本案例的其余部分。

当必须将异步响应发送到客户端时会发生什么情况?

Web 服务中的异步请求/响应模式不是传统的请求-响应。前面提到过,内部所发生的是客户端向服务器发送一个单向消息,服务器在必须做出响应时向客户端发回一个请求。客户端必须能够接收从服务器发回的请求。这全部显示在图 10 中。


bpel-amadei-fig10
图 10 — 使用 WS-A 的异步请求/响应


下面继续构建 soapUI 项目,来看看实际的回调案例。

测试它!

第一步是创建一个 Test Suite 并向其添加 Test Case。


  1. 右键单击 soapUI 项目并选择 New Test Suite,保留测试套件的默认建议名称。
  2. 右键单击 Test Suite 并选择 New Test Case,也保留建议的名称。
  3. 单击 OK

项目应类似于图 11。


bpel-amadei-fig11
图 11 — 具有 Test Suite 和 Test Case 的 SOAP UI

现在,执行以下操作向测试用例添加一个请求:


  1. 展开 AsyncBPELProcessBinding,继续并将 Request 1 拖到测试步骤窗格。
  2. 对所有 soapUI 提示进行回应。确认 soapUI 提示中的所有问题。
    这是测试的(几乎)所有请求部分。现在必须添加一种方式来接收响应:
  3. 右键单击 Test Case 1
  4. 选择 Add Test Step、Mock Response
  5. 将模拟响应命名为 Mock processResponse。将显示一个新窗口请您配置 Mock Response。
  6. 将接口更改为 AsyncBPELProcessCallbackBinding,这是用于回调的接口。
  7. 将操作保留为 processResponse — 这是唯一可用的选项。(如果流程支持多个异步响应 — 实际上是回调,可以在此步骤选择 soapUI 应模拟的操作。)
  8. 输入 9898 作为端口。SoapUI 将指示服务器开始在此 TCP/IP 端口监听。输入 /AsyncBPELProcessCallbackBinding/processResponse 作为 Path,它表示 URL 路径。

图 12 显示配置屏幕的最终状态。单击 OK


bpel-amadei-fig12
图 12 — SOAP UI MockResponse 配置

此时您可能会想,“BPEL 引擎如何了解它必须在我们刚配置的端口 [9898] 和路径 [/AsyncBPELProcessCallbackBinding/processResponse] 响应 soapUI?”由于 Oracle SOA Suite 和 soapUI 这两个工具均遵从标准,这可使用 WS-Addressing 轻松实现。

要指定 WS-Addressing 信息并通知 SOA Suite 在有响应要发送时如何回调 soapUI,请执行以下操作:


  1. 打开请求 process - Request 1
  2. 单击 WS-A 按钮并选中 Enable / Disable WS-A Addressing 复选框;
  3. Must understand 下拉菜单更改为 TRUE
  4. 选中 Add default wsa:Action 复选框;
  5. Reply To:部分,指定 http://localhost:9898/AsyncBPELProcessCallbackBinding/processResponse。这是我们在 soapUI 模拟响应的配置中指定的地址和路径;
  6. 选择 Randomly generate MessageId,以便随机生成消息 ID 以将请求与响应相关联。

WS-Addressing 配置应与图 13 相同。


bpel-amadei-fig13
图 13 — WS-Addressing 配置

再次打开 Test Case 并执行。两个步骤都顺利通过。通过打开 Mock processResponse 测试步骤,您应看到收到的响应。这显示 Oracle BPEL Process Manager 能够接收请求并回调 soapUI 以异步发送响应。您可以设置 XML 的格式以使其更易于阅读,如图 14 所示。


bpel-amadei-fig14
图 14 — 响应已收到!

单击 soapUI log 选项卡将显示以下消息,显示 soapUI 已启动一个服务器以接收请求(在路径 /AsyncBPELProcessCallbackBinding/processResponse 的端口 9898)并挂载了 WSDL 接口:


Sun Nov 13 20:55:40 BRST 2011:INFO:Mounted WSDL for interface [AsyncBPELProcessCallbackBinding] at
 [/AsyncBPELProcessCallbackBinding/processResponse?WSDL] 

Sun Nov 13 20:55:40 BRST 2011:INFO:Started mockService [Mock processResponse] on port [9898] at path
 [/AsyncBPELProcessCallbackBinding/processResponse] 

Sun Nov 13 20:55:40 BRST 2011:INFO:Stopped MockService [Mock processResponse] on port [9898]

为测试添加智能

我们能够发送请求并异步收回响应。但如何知道收到的是正确的响应?

这可以使用 soapUI 断言来实现。返回 Mock processResponse 测试步骤并单击 Assertions Tab。添加以下断言:


  1. SOAP 请求
  2. WS-Addressing 请求。按图 15 所示进行配置。

    bpel-amadei-fig15
    图 15 — 断言回调
    请求符合 WS-Addressing
  3. 添加 XPath Match 断言。此断言允许我们验证收到的请求回调。在 XPath Expression 部分,单击 Declare 按钮以便自动声明所有命名空间。找到命名空间……

    http://xmlns.oracle.com/OTNTestingAsyncBPEL/AsyncBPELProject/AsyncBPELProcess

    ……并注意其前缀。接下来,输入以下内容(仍在 XPath Expression 部分)……

    //<prefix>:processResponse/<prefix>:result

    ...其中 <prefix> 是所声明命名空间的前缀。例如,如果命名空间声明如下:

    declare namespace ns1='http://xmlns.oracle.com/OTNTestingAsyncBPEL/AsyncBPELProject/AsyncBPELProcess'

    ……您应指定 //ns1:processResponse/ns1:result 作为 XPath 字符串。

    现在可以指定我们希望在 <result> 元素中看到的值。该值应与请求中指定的一样:First test...。配置应类似于图 16。

bpel-amadei-fig16
图 16 — XPath Match 配置

为使其更有趣,还可以为请求添加一个断言。例如,可以测试所收到的 HTTP 代码是否为 202(已接受),意味着请求已被 Oracle SOA Suite 接受等待进一步处理。为此,添加名为 Valid HTTP Status Codes 的断言并指定 202 作为有效代码,如图 17 所示。


bpel-amadei-fig17
图 17 — 有效的 HTTP 返回代码

运行测试。您应看到测试用例的两个测试步骤均标为绿色,证明它们通过了添加的所有断言,如图 18 所示。


bpel-amadei-fig18
图 18 — 通过!

继续前进

以上演示的测试很有用。但对于实际使用,由于将相同的值用于请求和验证的响应,它就变得很单调且易于出错。在一个位置指定值岂不是更好?这在 soapUI 中非常容易实现。

实现这一目的的第一步是创建一个可以被所有测试步骤读取的属性。为此,打开测试用例并找到窗口左下侧的 Test Properties 选项卡,如图 19 所示。


bpel-amadei-fig19
图 19 — 测试属性

添加和使用属性:


  1. 单击加号图标并将属性命名为 requestValue
  2. 作为值,输入 123456
  3. 在请求上,将 <input> 元素的内容更改为 ${#TestCase#requestValue}。这是读取在测试用例级别指定的名为 requestValue 的属性的特殊指令。请求 SOAP 消息应类似如下:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
     xmlns:asy="http://xmlns.oracle.com/OTNTestingAsyncBPEL/AsyncBPELProject/AsyncBPELProcess">
       <soapenv:Header/>
       <soapenv:Body>
          <asy:process>
             <asy:input>${#TestCase#requestValue}</asy:input>
          </asy:process>
       </soapenv:Body>
    </soapenv:Envelope>
    
  4. 现在,返回 Mock processResponse 测试步骤,打开 XPath Match 断言并添加 ${#TestCase#requestValue} 作为预期结果,如图 20 所示。

    bpel-amadei-fig20
    图 20 — 基于测试用例
    属性的断言
  5. 现在,运行测试。它应完全成功。
  6. 返回 FMW Control。您应看到为该属性指定的值已经发送,如图 21 所示。

bpel-amadei-fig021
图 21 — 属性值正确发送到 BPEL 流程

总结

测试自动化是任何项目的基本功能。由于 Oracle SOA Suite 和 soapUI 中的 WS-Addressing 支持,您可以利用测试自动化来同时测试同步和异步流程。


Daniel Amadei 是巴西 Oracle Consulting 的首席顾问,是 SOA 和集成技术的专家。除了 SOA 的经验,他还从 1999 年就开始使用 Java 技术。Daniel 的认证资格包括 Oracle SOA 基金会从业人员、Oracle SOA 架构师认证专家和 Sun 认证企业架构师 (SCEA)。