首次发布者和 TDD 采用者。:-) 我会有点冗长,所以请耐心等待。

我最近开始使用 Apache CXF 框架、Spring 和 Commons Chain 来开发基于 SOAP 的 Web 服务来实现业务流程。我在这里面临的问题是测试 Web 服务——单元测试和功能测试中的测试。

我第一次尝试单元测试完全失败了。为了保持单元测试的灵活性,我使用了 Spring XML 文件来保存测试数据。另外,我没有创建要测试的“组件”实例,而是从 Spring 应用程序上下文中检索它们。包含数据的 XML 文件很快就失控了;在 XML 中创建对象图是一场噩梦。由于要测试的“组件”是从 Spring 应用程序上下文中选取的,因此每次测试运行都会加载 全部 我的应用程序中涉及的组件、使用的 DAO 对象等。此外,与集中或集中于仅测试组件的单元测试用例的概念相反,我的单元测试开始访问数据库、与邮件服务器通信等。糟糕,真的很糟糕。

我知道自己做错了什么,开始想办法改正。根据该板上的一篇帖子的建议,我查找了 Mockito,这是一个 Java 模拟框架,这样我就可以不用使用真正的 DAO 类和邮件服务器,而只需模拟功能。

随着单元测试的控制,这给我带来了第二个问题;对数据的依赖。我一直在开发的Web服务逻辑很少,但严重依赖数据。作为一个例子,考虑我的一个组件:

public class PaymentScheduleRetrievalComponent implements Command {
  public boolean execute(Context ctx) {
    Policy policy = (Policy)ctx.get("POLICY");
    List<PaymentSchedule> list = billingDAO.getPaymentStatementForPolicy(policy);
    ctx.put("PAYMENT_SCHEDULE_LIST", list);
    return false;
  }
}

我的大部分组件都遵循相同的路线——从上下文中选择一个域对象,点击 DAO [我们在这里使用 iBatis 作为 SQL 映射器]并检索结果。

那么,现在的问题是:
- 如何测试 DAO 类,特别是当单个插入或更新可能使数据库处于“不稳定”状态时[假设对不同表的 3 次插入实际上形成单个事务]?
- 移动大量数据的功能测试 Web 服务的事实标准是什么,即从数据存储中无意识地插入/检索?

您的个人经历/评论将不胜感激。如果我在解释当前问题时遗漏了一些细节,请告诉我。

-佐助

有帮助吗?

解决方案

我建议使用内存数据库来运行单元测试,例如HSQL。您可以使用它来动态创建架构(例如,如果您使用的是Hibernate,则可以使用XML映射文件),然后在单元测试结束时销毁数据库之前插入/更新/删除。您的测试决不会干扰您的实际数据库。

对于您的第二个问题(Web服务的端到端测试),我已经成功地对基于CXF的服务进行了单元测试。诀窍是在测试开始时使用轻量级Web服务器发布Web服务(Jetty是理想的),然后使用CXF将客户端指向Web服务端点,运行调用,最后关闭Jetty单元测试完成后托管Web服务的实例。

要实现此目的,您可以使用随CXF提供的JaxWsServerFactoryBean(服务器端)和JaxWsProxyFactoryBean(客户端)类,请参阅此页面以获取示例代码:

http:// cwiki .apache.org / CXF20DOC / A-简单JAX-WS-service.html#AsimpleJAX-WSservice-Publishingyourservice

我还要大肆宣传SOAP UI,以便对您的Web服务进行功能测试。 JMeter对于压力测试Web服务也非常有用,这对于那些进行数据库查找的服务来说非常重要。

其他提示

我会远离“Context as global hashmap”。如果我是你,那就是'模式'。

看起来你正在测试你的持久性映射...

您可能需要查看:测试没有弹簧的持久对象

首先:您是否有必要从Spring Application上下文中检索受测试的主题(SUT)?对于有效的单元测试,您应该能够在没有上下文的情况下创建SUT。听起来你在某处有一些隐藏的依赖。这可能是你头痛的根源。

  

在a时,如何测试DAO类esp   单次插入或更新可能   将数据库保留在“不稳定”状态。   国家[在让我们说3的情况下   插入到不同的表中   实际上形成一个单一的交易]?

运行测试后,您似乎担心数据库的常量。如果可能的话,使用自己的数据库进行测试,不需要关心它。如果您有这样的沙箱数据库,则可以根据需要删除数据。在这种情况下,我会做以下事情:

  1. 使用一些常用标识符标记所有虚假数据,例如为字段添加特殊前缀。
  2. 在运行测试之前,删除一个delete语句,删除标记的数据。如果没有,那就没什么不好的了。
  3. 运行您的单个DAO测试。之后重复步骤2.进行下一次测试。
  4.   

    什么是事实上的标准   功能测试Web服务   移动大量数据,即   无意识的插入/检索   数据存储?

    我不知道。从您提出的问题我可以推断出您一方面是Web服务,另一方面是数据库。分担责任。每侧都有单独的测试套件。一方只是测试数据库访问(如上所述)。另一方面,只测试Web服务请求和响应。在这种情况下,它支付存根/假/模拟与网络通信的层。或者考虑 https://wsunit.dev.java.net/

    如果程序只是推进和推出数据,我认为没有太多行为。如果是这种情况,那么最困难的工作是对数据库端和Web服务端进行单元测试。关键是你可以在不需要“现实”的情况下进行单元测试。数据。对于功能测试,您将需要手动数据,这与现实非常接近。这可能很麻烦,但如果您已经对数据库和Web服务部分进行了密集测试,则应该减少对“实际”部分的需求。测试案例相当多。

首先,把事情说清楚。

在理想的世界中,您正在构建的软件的生命周期是这样的:- sy 向客户报告,因此您得到了一个用户故事,其中包含有关应用程序应如何工作的示例 - 你概括了用户故事,所以你得到了规则,你称之为用例 - 你开始编写一个功能(端到端)测试,但它失败了......- 之后,您构建用户界面并模拟服务,这样您就得到了绿色功能测试和关于您的服务应如何工作的规范...- 你的工作是保持功能测试的绿色,并逐步实现服务,编写集成测试,并用相同的方法模拟依赖关系,直到你达到单元测试的水平 - 之后,你对用例进行下一次迭代,编写下一段功能测试,依此类推,直到项目结束 - 之后,您与接受产品并支付大量费用的客户进行验收测试

那么我们从中学到了什么:

  • 测试有很多种类型(不要将它们相互混淆)
    • 功能测试 - 用于测试用例(不模拟任何内容)
    • 集成测试 - 用于测试应用程序、组件、模块、类交互(模拟不相关的组件)
    • 单元测试 - 用于测试与其环境隔离的单个类(模拟所有内容)
    • 用户验收测试 - 客户确保她接受产品(手动功能测试,或在工作中通过自动功能测试进行演示)
  • 您不需要通过功能测试和集成测试来测试所有内容,因为这是不可能的。通过功能和集成测试仅测试相关部分,并通过单元测试测试所有内容!熟悉一下 测试金字塔.
  • 使用TDD,让生活更轻松!
  • 如何测试 DAO 类,尤其是当单次插入或更新可能会使数据库处于“不稳定”状态时 [在让我们 假设 3 个插入到不同的表中实际上形成了一个 交易]?

您不必测试数据库事务。假设它们运行良好,因为数据库开发人员已经测试了它们,并且我确信您不想编写并发测试......Db是一个外部组件,所以你不必自己测试。您可以编写数据访问层以使数据存储适应您的系统,并仅为这些适配器编写集成测试。在数据库迁移的情况下,这些测试也将由新数据库的适配器工作,因为您编写它们来实现特定的接口......通过任何其他测试(功能测试除外),您可以模拟数据访问层。对所有其他外部组件也执行相同的操作,编写适配器并模拟它们。将这些类型的集成测试放在与其他测试不同的测试套件中,因为它们由于数据库访问、文件系统访问等原因而很慢......

  • 功能测试 Web 服务的事实上的标准是什么,这些服务移动大量数据,即从数据存储中进行无意识的插入/检索?

您可以使用内存数据库模拟您的数据存储,该数据库实现相同的存储适配器,直到您实现除数据库之外的所有其他内容。之后,您实现数据库的数据访问层并通过功能测试对其进行测试。它会很慢,但它只能运行一次,例如每个新版本......如果您需要通过开发进行功能测试,您可以再次使用内存中的解决方案来模拟它......另一种方法是通过开发仅运行受影响的功能测试,或修改测试数据库的设置以使事情更快,等等......我确信有很多测试优化解决方案......

  

我必须说我真的不明白   你确切的问题。是问题   您的数据库保留在   运行后改变状态   测试

是的,这里实际上有两个问题。第一个是运行测试用例后数据库处于不一致状态的问题。第二个是我正在寻找一个优雅的Web服务端到端测试解决方案。

  

对于有效的单元测试,您应该   能够在没有的情况下创建SUT   上下文。听起来你有一些   某处隐藏的依赖关系。那   可能是你的一些人的根   头痛。

这确实是我头痛的根本原因,我现在要在一个模拟框架的帮助下废除它。

  

看来你很担心   你拥有数据库后的持久性   运行测试。如果可能的话使用a   你自己的数据库用于测试   不需要关心它。如果你有   您可以删除这样的沙箱数据库   你想要的数据。

这确实是我在上一篇文章中提到的问题的解决方案之一,但是在与所有数据库/数据不在您控制的遗留系统集成的情况下esp可能不适用于所有情况当某些DAO方法需要某个数据已经存在于给定的一组表中时。我应该研究像DBUnit这样的数据库单元测试框架吗?

  

在这种情况下它付出了代价   存根/假/模拟与之交谈的层   网络。或考虑一下    https://wsunit.dev.java.net/

啊,看起来很有趣。我也听说过SOAPUI等可以用于功能测试的工具。有没有人在这里使用过这样的工具?

感谢所有的答案和道歉的含糊不清的解释;英语不是我的第一语言。

-sasuke

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top