Web服务的端到端测试

时间:2009-05-01 18:46:40

标签: java testing service

第一次海报和TDD采用者。 :-)我会有点啰嗦,所以请耐心等待。

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

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

我知道我做错了什么,并开始想办法纠正它。根据该板上其中一个帖子的建议,我查找了Java模拟框架Mockito,以便我可以取消使用真正的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类esp [在假设3个插入到不同表中实际形成单个事务的情况下]? - 功能测试Web服务的事实上的标准是什么,它围绕大量数据移动,即从数据存储中无意识地插入/检索?

非常感谢您的个人经历/评论。如果我错过了解释手头问题的一些细节,请告诉我。

-sasuke

5 个答案:

答案 0 :(得分:2)

如果我是你,我会远离“作为全局散列图的上下文”'模式'。

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

您可能需要查看:testing persistent objects without spring

答案 1 :(得分:1)

首先:您是否有必要从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服务部分进行了密集测试,那么这将大大减少对“实际”测试用例的需求。

答案 2 :(得分:1)

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

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

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

http://cwiki.apache.org/CXF20DOC/a-simple-jax-ws-service.html#AsimpleJAX-WSservice-Publishingyourservice

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

答案 3 :(得分:1)

首先,明确一点。

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

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

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

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

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

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

答案 4 :(得分:0)

  

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

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

  

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

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

  

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

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

  

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

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

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

-sasuke