9

我正在使用BizUnit对我的 Biztalk 编排进行单元测试,但是一些编排使用 WebService,并且测试这些似乎更像是集成测试而不是单元测试。

我熟悉使用模拟框架来模拟生成的代理对象,以便从 Windows 窗体应用程序测试 Web 服务,但我希望能够在请求-响应端口中以更集成的方式完成它?

你会如何处理这个问题?

4

6 回答 6

8

这正是我作为 BizTalk 开发人员的主要烦恼之一——BizTalk 不适合进行单元测试。从您进入 BizTalk 应用程序的 99% 的接口是基于消息的并且有大量可能的输入这一事实,到编排的不透明性质,BizTalk 没有提供测试功能单元的真正方法......以及......单位。

对于 BizTalk,集成测试通常是唯一的游戏。

这导致,由于凯文史密斯没有过错,BizUnit 被 (IMO) 用词不当。一个更好的名字可能是 BizIntegrationIt。BizUnit 提供了一系列辅助集成测试的工具,其大部分测试,例如检查文件是否已写入给定目录或向 BizTalk HTTPReceive 位置发送 HTTPRequest 严格来说都是测试集成。

既然我已经吐槽了,你所要求的是我考虑了很长时间的东西,创建自动化单元测试的能力让我真正相信我对地图做一个小改动就赢了不要突然破坏下游的其他东西,以及消除对外部服务依赖的方法。

我从来没有想过这样做的任何好方法,但下面是一个应该可行的解决方案,我已经单独完成了每个部分的变体,但从未尝试过将它们全部以这种特定形式放在一起。

因此,鉴于希望模拟对某些外部服务(甚至可能还不存在)的调用,而不需要实际进行任何外部调用,并且希望能够设置对该服务调用的期望并指定响应的性质,我能想到的唯一方法是开发一个自定义适配器。

使用自定义适配器模拟 Web 服务

如果您构建一个自定义请求-响应适配器,您可以将其插入您的发送端口来代替 SOAP 适配器。然后,您可以为适配器指定属性,使其能够充当 Web 服务的模拟。该适配器在概念上类似于环回适配器,但允许内部模拟逻辑。

您可能希望作为适配器属性包含的内容:

  • 预期的文档(可能是一个磁盘位置,它指定了您希望 BizTalk 应用程序发送到 Web 服务的内容的示例)。
  • 响应文档 - 适配器将发送回消息传递引擎的文档。
  • 对测试的特定期望,例如文档元素中的查找值。

您还可以让自定义适配器写入磁盘并设置 BizUnit 步骤来验证写出的文件。

构建自定义适配器并非易事,但有可能,您可以从BizTalk 适配器向导获得良好的开端,这里有一篇关于部署自定义适配器的文章

向导生成的代码中有一个错误,您需要更改new Guid(""),new Guid().

还有一些在 BizTalk SDK 中构建自定义适配器的示例。

另一种选择是使用一个普通的 http 页面和这里讨论的 HTTP 请求响应,你的所有逻辑都在 http 页面中。如果您很高兴有一个 http 调用并设置一个 IIS 端口来监听您的测试,这可能会更简单。

初始化单元测试

您可以使用 .bat 文件将绑定文件导入 BizTalk 应用程序。

如果您为每个运行的测试以及标准应用程序设置创建一个新的绑定文件,那么您可以运行适当的批处理文件以应用正确的绑定。

每个绑定文件都会更改您的 Web 服务发送端口以使用模拟自定义适配器并为该测试设置特定属性。

然后,您甚至可以创建一个自定义 BizUnit 步骤,该步骤(可能)根据测试步骤中的设置生成绑定设置,然后运行 ​​shell 命令来更新绑定。

测试消息内容

您可能要考虑的最后一件事是将所有这些真正联系在一起,是测试消息内容的某种方式。您可以在模拟适配器中执行此操作,但对于大型消息或大量可能的输入消息,这将很快变得乏味。

一种选择是创建一个自定义管道,该管道调用Schematron来验证它接收到的文件。Schematron 是一种模式语言,它允许比 xsd 更丰富的文件检查级别,因此您可以检查诸如“如果元素 x 包含此内容,我希望元素 y 存在”之类的内容。

如果您构建了一个将 schematron 模式作为参数的自定义管道,那么您可以为特定的单元测试交换一个测试文件,验证该测试,当您调用 web 服务时,您会得到一个实际匹配您想要的文件(并且不只是匹配 xsd)

于 2008-11-07T02:20:05.290 回答
3

作为 BizUnitExtensions (www.codeplex.com/bizunitextensions) 的合著者,我同意 BizUnit 中的“单元”名称可能会造成混淆,但对于 Biztalk,“集成测试”是单元测试。一些 Biztalk 人员已经成功地使用模拟来测试管道组件和其他测试工具(+ BizUnit/Extensions)来测试模式和映射。

不幸的是,编排是不透明的。但这是有充分理由的。

(a) 由于消息框中的庞大订阅系统 - 编排在被激活时使用等,因此无法启动一些“虚拟”进程来托管编排(可以为管道完成。Tomas Restrepo 已经完成这些方面的东西)。

(b) 另外,这个虚拟进程将如何处理持久性和脱水?我敢打赌,使用 WF 的人在尝试完全测试工作流程时会遇到同样的问题。

(c) 我们不直接使用 C#,因此我们无法将模拟接口“注入”到编排代码中。

(d) 编排并不是真正的“单元”。它是一个复合元素。这些单元是进出消息框的消息以及通过表达式形状调用的外部组件。因此,即使您可以注入模拟 Web 服务接口,也无法注入模拟消息框和相关集等。

可以为编排做的一件事(我一直在考虑添加到 BizUnitExtensions 库来执行此操作)是与 OrchestrationProfiler 工具链接,因为该工具提供了所有形状的非常详细的报告,并以某种方式检查了个人步骤被执行(也许是执行所花费的时间)。这可能会使编排更像是一个白盒。另外考虑到编排调试器显示了很多变量值,当然必须可以通过 API 获取该信息以显示变量的值在给定实例的给定点。

回到 Richard 的问题,我之前的开发团队有一个解决方案。基本上我们所做的是编写一个通用的可配置 HttpHandler 来解析传入的服务请求并返回预设的响应。发回的响应可根据 XPath 等条件进行配置。在 BUILD 和 DEV 绑定文件中,webservice 端点是 mock。这在将 BUILD 和 DEV 环境与实际的第三方 Web 服务隔离开来时非常有效。这也有助于采用“合同优先”的方法,在这种方法中,我们构建了 mock,orch 开发人员使用它,而 web 服务作者继续构建实际的服务。

[更新:17-FEB-09:这个工具现在在 codeplex 上:http: //www.codeplex.com/mockingbird。如果这种方法听起来很有趣,请查看并告诉我您对该工具的看法]

现在,在有人抛出旧的“关于模拟对象框架的内容”栗子之前,让我说上面的实用程序既适用于 Biztalk 的“消费者”,也适用于非 Biztalk 的消费者,但我也与 NMock2 合作并发现在编写 CLR 消费者时,它是模拟接口和设定期望的绝佳方式。(我将很快研究 MoQ 和 TypeMock 等)。但是,由于上述原因,它不适用于编排。

希望这可以帮助。

问候,

本杰

于 2008-11-08T21:35:46.487 回答
1

不。

不要针对任意接口进行测试,也不要为它们创建模拟。

大多数人似乎认为开发人员(单元)测试旨在测试非平凡的、单独的功能单元,例如单个类。另一方面,对主要子系统或整个系统进行客户(验收/集成)测试也很重要。

对于 Web 服务,重要的功能单元隐藏在实际执行有意义服务的类中,位于通信线路后面。这些类应该有单独的开发人员测试类来验证它们的功能,但完全没有任何面向 Web 服务的通信线路。自然地,但可能不是很明显,这意味着您的功能实现必须与布线的实现分开。因此,您的开发人员(单元)测试永远不会看到任何特殊的通信线路;这是集成的一部分,可以(适当地)将其视为“演示”问题而不是“业务逻辑”。

客户(验收/集成)测试应该解决更大范围的功能,但仍然不关注“呈现”问题。这就是 Facade 模式的普遍使用——暴露一个具有统一的、粗粒度的、可测试的接口的子系统。同样,Web 服务通信集成是无关紧要的,并且是单独实现的。

但是,实现一组单独的测试非常有用,这些测试实际上确实包括 Web 服务集成。但我强烈建议不要只测试该集成的一方面:端到端测试。这意味着构建作为 Web 服务客户端的测试,就像真正的生产代码一样;他们应该完全按照实际应用程序的方式使用 Web 服务,这意味着这些测试可以作为任何必须实现此类应用程序的人的示例(例如,如果您正在销售库,则为您的客户)。

那么,为什么要这么麻烦呢?

  1. 您的开发人员测试验证您的功能在小范围内工作,无论它是如何访问的(独立于表示层,因为它都在业务逻辑层内)。

  2. 您的客户测试验证您的功能在您的业务逻辑层的接口边界处是否可以正常工作,无论它是如何访问的。

  3. 您的集成测试验证您的表示层与您的业务逻辑层一起使用,现在可以管理,因为您现在可以忽略底层功能(因为您在上面单独测试了它)。换句话说,这些测试集中在漂亮的面孔(GUI?)和通信接口(Web 服务?)的薄层上。

  4. 当您添加另一种访问功能的方法时,您只需为新的访问形式(表示层)添加集成测试。您的开发人员和客户测试可确保您的核心功能保持不变且完好无损。

  5. 您不需要任何特殊工具,例如专门用于 Web 服务的测试工具。您使用将在生产代码中使用的工具/组件/库/技术,就像在此类生产代码中使用它们一样。这使您的测试更有意义,因为您不是在测试其他人的工具。它可以为您节省大量时间和金钱,因为您无需购买、部署、开发和维护特殊工具。但是,如果您通过 GUI 进行测试(不要那样做!),您可能需要一个专门的工具用于该部分(例如,HttpUnit?)。

所以,让我们具体一点。假设我们想提供一些功能来跟踪自助餐厅的每日菜单(因为我们在一家大型公司工作,大楼里有自己的咖啡馆,就像我的一样)。假设我们的目标是 C#。

我们为菜单、菜单项和其他细粒度的功能及其相关数据构建了一些 C# 类。我们使用 nAnt 建立了一个自动构建(你这样做,对吗?),它使用 nUnit 执行开发人员测试,我们确认我们可以构建一个每日菜单并通过所有这些小块查看它。

我们对我们要去哪里有了一些想法,所以我们通过创建一个暴露少数方法同时隐藏大部分细粒度部分的单个类来应用 Facade 模式。我们添加了一组单独的客户测试,这些测试仅通过该新外观进行操作,就像客户一样。

现在我们决定要为我们的大型企业知识工作者提供一个网页来查看今天的自助餐厅菜单。我们编写一个 ASP.NET 页面,让它调用我们的外观类(如果我们使用 MVC,它将成为我们的模型),然后部署它。由于我们已经通过客户测试彻底测试了外观类,并且由于我们的单个网页非常简单,所以我们放弃针对网页编写自动化测试——使用一些知识工作者的手动测试就可以了。

后来,我们开始添加一些主要的新功能,比如能够预订我们当天的午餐。我们扩展了我们的细粒度类和相应的开发人员测试,因为我们知道我们预先存在的测试可以防止我们破坏现有的功能。同样,我们扩展我们的外观类,甚至可能随着接口的增长而分离出一个新类(例如,MenuFacade 和 OrderFacade),并在我们的客户测试中添加类似的内容。

现在,也许,对网站的更改(两个页面就是一个网站,对吗?)使手动测试无法令人满意。因此,我们引入了一个类似于 HttpUnit 的简单工具,它允许 nUnit 测试网页。我们实现了一系列集成/演示测试,但针对的是外观类的模拟版本,因为这里的重点是网页可以正常工作——我们已经知道外观类可以工作。测试通过模拟门面推送和拉取数据,只是为了测试数据是否成功到达另一端。而已。

当然,我们的巨大成功促使 CEO 要求(要求)我们将 Web 应用程序公开给大型公司的黑莓手机。因此,我们实现了一些新页面和一组新的集成测试。我们不必接触开发人员或客户测试,因为我们没有添加新的核心功能。

最后,CTO 要求(要求)我们将我们的自助餐厅应用程序扩展到所有 mega-corp 的机器人工人——你在过去几天注意到他们了吗?所以,现在我们添加一个通过我们的外观进行通信的 Web 服务层。同样,我们的核心功能、我们的开发人员测试或我们的客户测试没有任何变化。我们通过创建使用等效 Web 服务 API 公开外观的类来应用适配器/包装器模式,并且我们创建客户端类来使用该 API。我们添加了一组新的集成测试,但它们使用普通的 nUnit 创建客户端 API 类,这些类通过 Web 服务连接与服务端 API 类进行通信,服务端 API 类调用模拟外观类,从而确认我们的连接工作。

请注意,在整个过程中,除了我们的生产平台和代码、我们选择的开发平台、一些用于自动化构建和测试的开源组件以及一些定义明确的测试组之外,我们不需要任何重要的东西。另请注意,我们没有测试任何我们在生产中不使用的东西,我们也没有测试任何东西两次。

我们最终得到了一个已经证明自己成熟(假设)的功能的坚实核心(业务逻辑层)。我们有三个独立的表示层实现:一个针对桌面的网站、一个针对黑莓的网站和一个 Web 服务 API。

现在,请原谅我的冗长答案——我厌倦了不充分的答案,我不想提供一个。请注意,我实际上已经这样做了(尽管不是自助餐厅菜单)。

于 2008-11-07T01:18:15.663 回答
0

这是一个非常有趣的问题,我仍然没有看到一个好的通用答案。有些人建议使用 SoapUI,但我还没有时间实际测试它。这个页面可能对此很有趣。

另一种方法可能是以某种方式包装 WebDev.WebHost.dll 并使用它... Phil Hakkck 在这篇文章中讨论了这一点。

之前也在这里讨论过。

如果您找到其他解决方案,请告诉我们!

于 2008-11-04T13:30:29.573 回答
0

这是这样做的方法:

回到 Richard 的问题,我之前的开发团队有一个解决方案。基本上我们所做的是编写一个通用的可配置 HttpHandler 来解析传入的服务请求并返回预设的响应。发回的响应可根据 XPath 等条件进行配置

于 2008-11-26T13:25:32.143 回答
-1

我已经有一段时间不用这样做了,但是当我测试我的 Biztalk 应用程序时,我总是使用soap ui 或 web service studio。我能够毫不费力地测试不同的输入值。

于 2008-11-04T19:32:31.137 回答