【问题标题】:Create an in-memory database structure from an Oracle instance从 Oracle 实例创建内存数据库结构
【发布时间】:2011-04-16 15:18:27
【问题描述】:

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

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

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

我的问题是知道什么是最好的方法。我主要关心的是内存数据库结构的构建和引用数据的插入。

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


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

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

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);

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


所以我的问题:

  • 您可以给我什么建议来实现这一目标?
  • h2hsqldb 是否提供一些工具来从 Oracle 连接生成脚本?

技术资料

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


编辑

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    您的单元测试是为了什么? 如果他们测试 DDL 和存储过程的正常工作,那么您应该编写更接近 Oracle 的测试:要么没有 Java 代码,要么没有 Spring 和其他漂亮的 Web 界面,完全专注于 db。

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

    如果您想测试整体的工作情况(这违反了模块化开发和测试原则),那么您可以虚拟化您的数据库并在该实例上进行测试,而不会冒进行一些令人讨厌的不可逆修改的风险。

    【讨论】:

    • 我已经编辑了我的问题,以便更准确地了解我为什么要使用内存数据库。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 鉴于 DAO 代码似乎与 Oracle 紧密耦合,并且 DAO 无法抽象出来,这似乎是最好的方法——尽管希望 DAO 代码不依赖于任何 Oracle 特性。最好尽快抽象出 DAO...
    • 向@Thomas 提出一个问题:H2 现在是否支持 Oracle“从...开始连接”?想要针对 H2 测试该语法,但似乎还没有。
    • @WesternGun 对不起,我不知道。
    【解决方案3】:

    最新的 HSQLDB 2.0.1 通过语法兼容性标志 sql.syntax_ora=true 支持 DUAL、ROWNUM、NEXTVAL 和 CURRVAL 的 ORACLE 语法。以同样的方式,字符串与 NULL 字符串的连接以及 UNIQUE 约束中对 NULL 的限制由其他标志处理。 TO_CHAR、TO_DATE、NVL等大部分ORACLE函数已经内置。

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

    将类型编号创建为数字

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

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

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

    【讨论】:

      【解决方案4】:

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

      不兼容似乎很小,但不久之后真的会反咬一口。在一个好的情况下,你可能会摆脱一些讨厌的 sql 翻译/广泛的嘲弄。在糟糕的情况下,系统的某些部分将无法测试,我认为这对于关键业务系统来说是不可接受的风险。

      【讨论】:

      • "对真实数据库运行测试没有任何问题"。我不同意这一点。使用真正的数据库进行单元 测试并不是一个好主意,至少有两个原因:1. 您的测试依赖于您的数据库,并且可能仅因为您的数据库关闭而失败。 2. 创建与真实数据库的连接更昂贵,当您谈论数百个测试时,它们的执行将是一个问题。尤其是在 TDD 方式中。
      • 当然,拥有访问真实数据库的测试也是一个好主意,但我们处理的不是单元测试,而是更多集成 测试。这不是我的意思。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多