`
zhangziyangup
  • 浏览: 1076811 次
文章分类
社区版块
存档分类
最新评论

使用 JdbcProxy 测试 Java 应用程序

 
阅读更多

在我们测试 Java 应用程序时,往往需要连接数据库,并从数据库中获得准确的测试数据用以测试应用程序是否正确。然而准备测试数据的工作较为复杂,一旦数据库中的数据发生变化,要想恢复到之前的版本也很费时。对于那些没有条件连接数据库的测试者而言,测试工作是不能进行下去的。因此,如果可以为某个待测应用准备一套完备的测试数据,让程序开发、测试人员在不依赖于具体数据库的情况下对应用进行测试,这无疑是十分方便的。

简介

JdbcProxy 是 SourceForge 上一个开源的 Java 项目,用 Java 语言编写,遵循 LGPL 和 MPL1.1 协议,由 Frans van Gool 开发,支持 JDBC2.0 规范。通过继承和重写 JDBC2.0 的接口,将一个 Java 应用访问数据库的过程记录在 XML 文件中,并通过这些文件在脱离数据库的情况下重现这个调用过程。 JdbcProxy 可以用在 Java 应用程序的测试中,进行数据准备并模拟数据库调用过程。读者可以从 JdbcProxy 主页 获得最新的程序源代码以及说明文档。目前最新的版本是 1.1 。

使用 JdbcProxy 代替普通的数据库调用可以满足程序开发、测试人员的很多需求,使准备测试数据的工作变得简单。以文章查询系统为例,有些测试用例需要测试当数据库中没有数据时页面的显示情况——显示没有相应数据的页面;有些测试用例需要测试当数据库中只有一条数据时页面的显示情况——显示文章的内容而不是文章的列表;还有些测试用例需要测试页面的分页效果,这时就需要为程序准备不同的测试数据。如果采用直接连接测试用数据库的方式进行测试,不同的测试用例需要重新准备测试数据库,操作起来比较复杂,也不能同时测试不同的测试场景。如果使用 JdbcProxy,就可以为同一个 Java 程序准备不同的测试用数据文件,测试者可以脱离后端数据库的限制,只需要访问到数据文件就能完成测试。不同测试人员能够彼此不受影响的同时测试这个应用,从而大大简化了准备测试环境的过程。

使用 JdbcProxy

JdbcProxy 提供了两种记录 JDBC 调用过程的方式,一种是方便开发人员和测试人员阅读的,另一种是用于回放 JDBC 调用过程的

第一种方式主要是为了让开发人员和测试人员能够了解 Java 应用调用 JDBC 的详细信息,当应用程序较为复杂——例如进行了多表查询,采用这种记录方式可以让开发人员和测试人员一目了然的看到应用程序访问数据库的过程。

第二种方式是为测试程序准备数据的关键步骤之一。为了回放 JDBC 调用过程,JdbcProxy 分别处理应用程序对数据库的每个请求 (request) 与响应 (response),并在指定目录下生成一系列 XML 文件,这些文件是回放 JDBC 调用过程的基础。这些 request/response 文件并不能直接被 JdbcProxy 调用,JdbcProxy 还提供了一个 StubTraceMerger 工具,用来将这些 request/response 文件整合在一个文件中,这个整合的文件就是我们测试 Java 应用所需要的数据文件。

JdbcProxy 提供了一种通过 HTTP 服务器发送请求并接收响应的机制,这些请求和响应都按照应用程序的 JDBC 调用顺序记录在整合文件中,当 Java 应用试图通过 JDBC 连接数据库时,JdbcProxy 会通过 HTTP 服务器从整合文件中读取相应的数据,模拟调用数据库的过程,使用户得以在脱离数据库的情况下进行 Java 应用的测试。

因此要想利用 JdbcProxy 测试 Java 应用程序,首先需要生成用于回放 JDBC 调用过程的 request/response 文件,然后将这些 request/response 文件整合在一个文件中,最后将这个整合的数据文件提供给 HTTP 服务器,这样 JdbcProxy 就可以通过 HTTP 服务器访问到数据文件,实现脱离数据库进行测试的目的。

下面将对 JdbcProxy 提供的每个功能做详细的介绍。

记录方便开发人员和测试人员阅读的 JDBC 调用过程

JdbcProxy 可以跟踪 JDBC 调用过程,生成方便开发人员和测试人员阅读的文件格式。在普通的数据库调用中,如果开发人员和测试人员想了解 JDBC 的调用过程,或者需要完整的查看某个 SQL 语句,则需要手工将这些信息打印出来或者记录在日志中。 JdbcProxy 的这个功能就像为 JDBC 的调用过程自动记录了一个日志,开发人员和测试人员可以从日志中获得被调用的每一个方法,以及调用方法的参数和返回值。这样便于开发人员和测试人员发现由于 SQL 语句拼写错误而导致的数据库访问失败,或是由于数据库中没有数据而导致的空指针异常,使应用程序的数据库访问过程更加直观。可以根据清单 1中的示例代码生成 JDBC 调用过程。


清单 1

与普通数据库调用不同,清单 1中示例程序中所需的数据库驱动是 JdbcProxy 提供的StubTracerDriver,URL 的结构如下:

jdbc:tracer:<filename>:<driver>:<url>

其中:

  • <filename> 是保存结果的文件名;如果为空,结果会被输出到控制台。
  • <driver> 是数据库驱动名,该示例程序使用的是 db2 的驱动。
  • <url> 是数据源的 URL,该示例程序使用 jdbc:db2:SAMPLE,不需要用户名和密码。

运行上述程序得到清单 2的记录结果:


清单 2

可以看到,JdbcProxy 记录下了每一个 JDBC 调用的参数和返回值,可以很容易的通过这些值判断出程序在什么地方出现问题。如果运行过程中出现异常,JdbcProxy 还可以将抛出的异常记录下来。

记录用于回放的 JDBC 调用过程

方便开发人员和测试人员阅读的 JDBC 调用过程其记录形式不便于进行解析,因此并不能直接被用来回放的 JDBC 调用过程。为了简化准备数据的过程,JdbcProxy 还可以生成一种用于回放 JDBC 调用过程的,特别是易于在 HTTP 服务器上使用的记录文件。在运行新的程序之前,我们首先需要新建一个空的文件夹 output 用来存放 JdbcProxy 生成的一系列 request/response 文件,然后将 url 做以下修改,如 清单 3 所示。


清单 3

				
String url = "jdbc:stubtracer:output:COM.ibm.db2.jdbc.app.DB2Driver:jdbc:db2:SAMPLE";

URL 结构如下:

jdbc:stubtracer:<foldername>:<driver>:<url>

其中:

  • <foldername> 是输出 request/response 文件的位置;如果为空则将文件内容输出到控制台。
  • <driver> 是数据库驱动名,该示例程序使用的是 DB2 的驱动。
  • <url> 是数据源的 URL,该示例程序使用 jdbc:db2:SAMPLE,不需要用户名和密码。

运行上述程序会在指定目录下生成 32 个以 request/response 开头的文本文件,如图 1所示。


图 1. request/response 文件

这些文件包含了回放 JDBC 调用过程所需的所有请求和响应。以建立 Connection 的请求为例,该示例程序对数据库的第一个请求就是建立 Connection,这个过程记录在 request_0_0.txt 文件中,参见清单 4。其中文件名中的 2 个“ 0 ”分别代表本次 JDBC 调用的 id 和 status,调用的方法是 connect 。


清单 4

JdbcProxy 会根据 request 文件中 id 和 status 的值找到对应的 response 文件,在本例中为 response_0_0.txt,参见清单 5。在 response_0_0.txt 中,我们看到已经新建了一个 java.sql.Connection 的对象,并且指定了下一个请求的 id 和 status 。


清单 5

整合 request/response 文件

在上面生成的 request/response 文件还需要进行整合才能提供给 HTTP 服务器用于回放 JDBC 调用过程。可以使用 StubTraceMerger 工具将一系列 request/response 文件整合成一个文件。整合文件需要运行的命令如清单 6所示。


清单 6

				
StubTracerMerger output

该命令的结构如下:

StubTracerMerger <foldername>[<id>[<status>] ]

其中:

  • <foldername> 是 request/response 文件存放的位置,不可为空。
  • <id> 是需要整合的初始响应的 id,默认值为 0,即整合完整的 JDBC 调用过程。
  • <status> 是需要整合的初始响应的 status,默认值为 0 。

运行上述命令,StubTracerMerger 会将所有 request/response 文件的内容按照调用的顺序整合在一个 <response> 元素下,并在控制台上输出一段整合的 XML 文件。从 XML 文件中,我们能够看到 StubTracerMerger 将新建的 Connection,Statement 以及 ResultSet 对象记录在 ProxyObject 结点中,调用的方法则被记录在 requestresponse 结点。例如:java.sql.Connection 调用了 createStatement() 以及 close() 两个方法,所以 Connection 的 ProxyObject 结点中包含了两个 requestresponse 子结点;生成的 java.sql.Statement 分别进行了删除、添加、修改、查询,以及关闭 Statement 操作,因此该结点包含 5 个 requestresponse 子结点。其中 id 代表对象的标识,status 代表该对象状态,初始值为 0 。按照这种方式,JdbcProxy 将 Java 应用程序调用 JDBC 访问数据库的过程记录成了一个 XML 文件。清单 7中给出一段执行删除操作的示例,读者可以在文章最后的 下载 区下载到完整的 XML 文件。


清单 7

通过 HTTP 服务器回放 JDBC 调用过程

JdbcProxy 提供了通过 HTTP 服务器回放 JDBC 调用过程的方式,即用户只需要将准备好的数据文件提供给 HTTP 服务器就可以在脱离数据库的情况下模拟对数据库的访问,完成 Java 应用的测试。如果想通过 HTTP 服务器回放 JDBC 调用过程,只需要修改示例程序中的 url,如清单 8所示。


清单 8

				
String url = "jdbc:stub:localhost:80:1000";

URL 结构如下:

jdbc:stub:<hostname>:<port>:<timeout>

其中:

  • <hostname> 是 HTTP 服务器的主机名,本地机器为 localhost 。
  • <port> 是 HTTP 服务器的端口号。
  • <timeout> 是超时时间,单位是毫秒。

在该示例程序中我们采用 Apache 的 HTTP server 2.2.4,使用默认端口 80 。用整合的数据文件替换 /htdocs 目录下的默认欢迎页面,这样 HTTP 服务器就可以从本地 80 端口接收请求并在数据文件中匹配到相应的 response,将 response 内容返回给 Java 应用程序。我们可以在控制台得到与直接连接数据库时相同的返回结果,JdbcProxy 可以通过预先准备好的数据文件,在不连接数据库的情况下通过 HTTP 服务器获得准确的响应数据,测试 Java 应用程序是否能够正确执行。

开发人员和测试人员可以通过修改整合的数据来获得不同的测试场景,例如按照整合文件的数据格式添加新的数据、删除多余的数据、或是修改数据的类型,用来构建不同的测试用例,满足不同测试的需要。

改进 JdbcProxy

在整合 request/response 文件时,JdbcProxy 只能将整合的数据文件输出到控制台,这种输出方式非常不利于在回放过程中使用。如果可以直接将其输入到 /htdocs 目录下的默认文件中,则省去了每次移动文件的麻烦。另外,JdbcProxy 只提供通过 HTTP 服务器回放 JDBC 调用过程的方式,必须有 HTTP 服务器的支持。因此,我们对 JdbcProxy 进行了一些改进,首先可以将整合的文件直接输出到指定目录下,其次可以不依靠 HTTP 服务器直接从整合文件中获取 JDBC 响应。

下面将介绍如何直接生成整合文件以及通过整合文件回放 JDBC 调用过程。

直接生成整合文件

在生成整合文件时,我们可以省去一系列生成 request/response 文件的步骤,直接将每个 request 和 response 存储于一个静态的 TreeMap 中,再将 TreeMap 中的内容整合并按照指定路径输出到文件中。这样做可以大大节省依次读取每个 request/response 文件所需要的时间,提高程序运行的效率。同时,可以自行指定整合文件的输出位置,不需要手动将整合的数据文件内容从控制台复制到 /htdocs 目录下的默认欢迎页面,在一定程度上减少了工作量。此处的改动包括:修改了 StubTracerHandler 类的 invoke 方法,在 nl.griffelservices.proxy.stub 包下增加了 FileStubTracerMerger 类,demo 包下增加了 GenerateMergerFile 类。

在运行程序之前,需要先将 StubTracerHandler 类的 invoke 方法做如下修改:

tracer.trace(request, response);

改成

new FileStubTracerMerger(map,request,response);

以便直接从内存中读取 response 生成整合文件。此外还需要运行下面程序,如清单 9所示。


清单 9

其中所需要的 driver 与前面记录用于回放的 JDBC 调用过程中的 driver 相同,url 则不需要提供 foldername 。另外还要在程序的最后加入两行代码,GenerateMergerFile 方法所需的参数即整合文件的相对路径和文件名。运行上述程序,在 output 目录下会生成名为 mergerfile.xml 的整合文件,mergerfile.xml 即为测试 Java 应用程序所准备的数据文件。

通过整合文件回放调用过程

对于直接通过整合文件回放 JDBC 调用过程的问题,我们重写了 JdbcProxy 中的一些方法。依然使用前面的示例程序,如果采用这种方式回放调用过程,我们要修改 driver 和 url 两个参数,如清单 10所示。


清单 10

				
 String driver = "nl.griffelservices.proxy.jdbc.oracle.FileStubTracerDriver"; 
 String url = "jdbc:stub:output/mergerfile.xml";

通过对这两个参数的修改,JdbcProxy 将调用我们重写的方法,不需要通过 HTTP 服务器而是直接从整合文件中获取程序所需的响应结果。此处的改动包括:在 nl.griffelservices.proxy.stub 包下增加了 FileClient、FileStub、FileStubHandler、FileStubTracerMerger 四个类,在 nl.griffelservices.proxy.jdbc.oracle 包下增加了 FileStubTracerDriver 类,在 nl.griffelservices.proxy.jdbc.util 包下增加了 FileCombinedHandler 类。我们主要修改了 FileCombinedHandler 类中的 DriverUrl 方法用于解析新的参数;修改了 FileClient 类中的 invoke 方法用于从整合文件中读取相应的 response 。读者可以从文章最后的下载区中下载修改后的代码。

此时数据库驱动是我们改写的提供的FileStubTracerDriver,URL 的结构如下:

jdbc:stub:<filepath>

其中:

  • <filepath> 是整合文件的相对路径和文件名。

运行上述程序,我们可以在控制台得到与直接连接数据库时相同的返回结果,不必通过 HTTP 服务器 JdbcProxy 也可以进行 Java 应用的测试。

结语

JdbcProxy 可以让程序开发人员和测试人员脱离数据库的限制完成测试工作。如果测试工作需要多人共同完成,那么采用 HTTP 服务器的方式能够保证数据的一致性,更加便于小组成员协作;如果准备数据以及测试程序的工作由同一人完成,那么通过整合文件的方式则更加直接,能够提高程序运行的效率。

本文以一个实例介绍了 JdbcProxy 的基本功能,以及如何使用 JdbcProxy 进行数据的准备和测试。考虑到 JdbcProxy 只能通过 HTTP 服务器回放 JDBC 访问,本文还对 JdbcProxy 进行了改进,提供了直接通过整合的数据文件进行回放的方式。您可以根据实际情况选择合适的回放方式,参照这个实例对 JdbcProxy 进行修改,来测试您的 Java 应用程序,实现脱离数据库的测试工作。

值得注意的是,我们并不能保证本文所提出的使用 JdbcProxy 测试 Java 应用程序的方法可以完美地解决所有的问题。如果读者希望采用本方案,请参考 JdbcProxy 的文档以了解更多的信息。

分享到:
评论

相关推荐

    JDBC,MySQL和JDBCProxy联合实现Java数据库.pdf

    JDBC,MySQL和JDBCProxy联合实现Java数据库.pdf

    JdbcProxyTest

    JdbcProxy 示例程序 JdbcProxy 可以理解为 JDBC 代理,是一个开源的 JDBC 项目。...本文将以一个具体的 Java 应用为例,演示如何使用 JdbcProxy 记录和重现 JDBC 访问,实现 Java 应用的测试工作。

    Java 代理(proxy)模式

     代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个...

    JdbcProxy - To trace and stub JDBC calls-开源

    JdbcProxy是JDBC 2.0驱动程序,可以帮助调试或测试应用程序。 该驱动程序可以包装另一个JDBC驱动程序,以调试应用程序完成的JDBC调用。 该驱动程序还可以模拟另一个JDBC驱动程序,以在没有数据库的情况下测试应用...

    Toxi / Oxy Pro 便携式气体检测仪参考手册 使用说明书

    Toxi Oxy Pro 便携式气体检测仪参考手册 使用说明书

    科傻模拟网优化操作-教程书

    官方的的说明书资料,部分视频说明在这里: https://www.bilibili.com/video/BV1Fz4y1d7rn/?spm_id_from=333.999.0.0&vd_source=13dc65dbb4ac9127d9af36e7b281220e

    node-v8.14.0-x64.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    2023商业银行数据资产体系白皮书,主要介绍了“三位一体”数据资产体系的构成与工作机制,以及商业银行数据资产体系建设实践

    2023商业银行数据资产体系白皮书 目录 第 1 章 数据资产化与数据要素市场化相辅相成,相互促进 第 2 章 数据资产化是企业数据治理向上演进的必经之路 第 3 章 数据资产体系发展概述 第 4 章 “三位一体”数据资产体系的构思 4.1“三位一体”数据资产体系的构成与工作机制 数据资产管理 数据资产运营 数据资产评价 数据资产体系工作机制 4.2“三位一体”数据资产体系的相互作用关系 4.3“三位一体”数据资产体系的构建 4.4“三位一体”数据资产体系的优势 第 5 章 商业银行数据资产体系建设实践 5.1商业银行开展数据资产体系建设的背景和目标 5.2商业银行数据资产体系建设的工作步骤 5.3上海银行数据资产体系建设实践的主要成果 第 6 章 数据要素流通市场赋能企业数据资产化 6.1全国多层次数据要素市场的建设 6.2上海数据交易所赋能企业数据资产化 6.3数据要素流通交易市场赋能企业数据资产化的展望 第 7 章 未来演进与展望

    基于微信小程序的助农扶贫小程序

    大学生毕业设计、大学生课程设计作业

    车辆销售数据Python爬取并做数据分析,项目源码注解清晰一看就懂.zip

    车辆销售数据Python爬取并做数据分析,项目源码注解清晰一看就懂

    毕业设计:基于SSM的mysql-学生社团管理系统(源码 + 数据库 + 说明文档)

    毕业设计:基于SSM的mysql_学生社团管理系统(源码 + 数据库 + 说明文档) 第2章 主要技术和工具介绍 1 2.1 JSP语言 1 2.2 MySQL数据库 1 2.3 jsp技术 2 2.4ssm简介 3 第3章 系统分析 1 3.1可行性分析 1 3.1.1经济可行性 1 3.1.2技术可行性 1 3.1.3操作可行性 1 3.2需求分析 1 3.3业务流程分析 2 3.4数据流程分析 3 第4章 系统设计 5 4.1系统结构设计 5 4.2功能模块设计 5 4.3数据库设计 6 4.3.1数据库设计概述 6 4.3.1概念设计 6 4.3.2表设计 7 第5章 系统实现 15 5.1基本任务 15 5.2登录模块的实现 15 5.2.1首页实现 15 5.2.2管理员后台登录 16 5.3用户模块的实现 19 5.3.1注册模块及登录的实现 19 5.2.2入团模块的实现 21 5.2.3场地预约模块的实现 22 5.4管理员模块的实现 24 5.4.1系统用户管理模块的实现 24 5.4.2活动公告管理模块的实现 26 5.5社团模块的实现 28 5.5.1活动信息

    大健康零售业务O2O数字化战略规划方案.pptx

    大健康零售业务O2O数字化战略规划方案.pptx

    数据中台项目主要岗位及其职责和任务

    数据中台项目主要岗位及其职责和任务

    node-v8.0.0-linux-armv7l.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    流程制造行业数字化智能工厂总体规划建设方案.pptx

    流程制造行业数字化智能工厂总体规划建设方案.pptx

    c语言学生成绩管理系统源码.zip

    c语言学生成绩管理系统源码.zip

    DEV-C++-5.11下载链接

    DEV-C++-5.11下载链接

    电器租赁小程序.zip

    电器租赁小程序.zip

    学生成绩管理系统 数据结构与算法课程设计 C++.zip

    学生成绩管理系统 数据结构与算法课程设计 C++

    知乎小程序算法.zip

    知乎小程序算法.zip

Global site tag (gtag.js) - Google Analytics