从Oracle实例创建内存数据库结构

时间:2010-09-24 06:53:36

标签: java unit-testing hsqldb h2 in-memory-database

我有一个应用程序,其中许多“unit”测试在执行期间使用与Oracle数据库的真实连接。

可以想象,这些测试需要花费太多时间来执行,因为它们需要初始化一些Spring上下文,并与Oracle实例进行通信。除此之外,我们还必须管理复杂的机制,例如事务,以避免在测试执行后修改数据库(即使我们使用Spring中的有用类,如AbstractAnnotationAwareTransactionalTests)。

所以我的想法是逐步用内存数据库替换这个Oracle测试实例。我会使用hsqldb或更好h2

我的问题是要知道这样做的最佳方法是什么。我主要关心的是构建内存数据库结构和插入参考数据。

当然,我可以使用SQL DeveloperTOAD之类的工具从Oracle中提取数据库结构,然后修改这些脚本以使其适应hsqldb或{{1 }} 语言。但我认为这不是更好的方法。


事实上,我已经在使用h2的另一个项目上做了这个,但是我已经手动编写了所有脚本来创建表。幸运的是,我只创建了几张桌子。我在这一步中遇到的主要问题是将用于创建表的Oracle脚本“翻译”为hsqldb语言。

例如,使用以下sql命令在Oracle中创建的表:

hsqldb

需要将CREATE TABLE FOOBAR ( SOME_ID NUMBER, SOME_DATE DATE, -- Add primary key constraint SOME_STATUS NUMBER, SOME_FLAG NUMBER(1) DEFAULT 0 NOT NULL); “翻译”为:

hsqldb

在我目前的项目中,有太多的表要手动执行...


所以我的问题:

  • 您可以给我什么建议来实现这一目标?
  • CREATE TABLE FOOBAR ( SOME_ID NUMERIC, SOME_DATE TIMESTAMP PRIMARY KEY, SOME_STATUS NUMERIC, SOME_FLAG INTEGER DEFAULT 0 NOT NULL); h2是否提供了一些从Oracle连接生成脚本的工具?

技术信息

Java 1.6,Spring 2.5,Oracle 10.g,Maven 2


修改

有关我的单元测试的一些信息:

在我使用hsqldb的应用程序中,我进行了以下测试: - 一些“基本”单元测试,与DB无关。 - 对于DAO测试,我使用hsqldb来执行数据库操作,例如CRUD。 - 然后,在服务层,我使用hsqldb来模拟我的DAO对象,以便专注于服务测试而不是整个应用程序(即service + dao + DB)。

在我目前的应用程序中,我们遇到了最糟糕的情况:DAO层测试需要运行Oracle连接。服务层使用(还)任何模拟对象来模拟DAO。因此服务测试需要Oracle连接。

我知道模拟和内存数据库是两个分离点,我会尽快解决它们。但是,我的第一步是尝试通过内存数据库删除Oracle连接,然后我将使用我的Mockito知识来增强测试。

请注意,我还想将单元测试与集成测试分开。后者需要访问Oracle数据库,才能执行“真正的”测试,但我主要关注的问题(这就是这个问题的目的)是几乎所有的单元测试都不是今天孤立运行的。

4 个答案:

答案 0 :(得分:19)

使用内存/ Java数据库进行测试。这将确保测试比您在测试中“抽象”数据库时更接近现实世界。可能这样的测试也更容易编写和维护。另一方面,您可能希望在测试中“抽象化”的是UI,因为UI测试通常难以自动化。

您发布的Oracle语法适用于H2数据库(我刚测试过),因此H2似乎比HSQLDB更好地支持Oracle语法。免责声明:我是H2的作者之一。如果某些内容无效,请将其发布在H2邮件列表中。

无论如何,您应该在版本控制系统中拥有数据库的DDL语句。您也可以使用这些脚本进行测试。可能您还需要支持多个模式版本 - 在这种情况下,您可以编写版本更新脚本(alter table ...)。使用Java数据库,您也可以测试它们。

顺便说一句,在使用H2或HSQLDB时,您不一定需要使用内存模式。即使您持久保存数据,这两个数据库也都很快。而且它们易于安装(只是一个jar文件),并且需要比Oracle少得多的内存。

答案 1 :(得分:4)

最新的HSQLDB 2.0.1通过语法兼容性标志sql.syntax_ora = true支持DUAL,ROWNUM,NEXTVAL和CURRVAL的ORACLE语法。以相同的方式,使用其他标志处理字符串与NULL字符串的串联以及对UNIQUE约束中的NULL的限制。大多数ORACLE函数(如TO_CHAR,TO_DATE,NVL等)都已内置。

目前,要使用简单的ORACLE类型(如NUMBER),您可以使用类型定义:

将类型编号设为数字

设置标志时,下一个快照将允许NUMBER(N)和ORACLE类型兼容性的其他方面。

http://hsqldb.org/support/下载

[更新:] 10月4日发布的快照将大多数Oracle特定类型转换为ANSI SQL类型。 HSQLDB 2.0也支持ANSI SQL INTERVAL类型和日期/时间戳算法,与Oracle相同。

答案 2 :(得分:2)

您的单元测试是什么? 如果他们测试DDL和存储过程的正常工作,那么你应该将测试编写为“更接近”Oracle:要么没有Java代码,要么没有Spring和其他优秀的Web界面,而是关注数据库。

如果您想测试在Java和Spring中实现的应用程序逻辑,那么您可以使用模拟对象/数据库连接来使您的测试独立于数据库。

如果你想测试整个工作(什么是模块化开发和测试原则)那么你可以虚拟化你的数据库并测试该实例,而不会有做一些令人讨厌的不可逆修改的风险。

答案 3 :(得分:1)

只要您的测试自行清理(因为您似乎已经知道如何设置),对真实数据库实例运行测试没有任何问题。事实上,这是我通常喜欢的方法,因为你将尽可能接近生产测试。

不兼容性似乎很小,但实际上最终还是不久就咬了一口。在一个好的情况下,你可能会逃避一些讨厌的SQL翻译/广泛的嘲弄。在不好的情况下,系统的某些部分将无法进行测试,我认为这对业务关键型系统来说是不可接受的风险。