H2 postgresql模式似乎不适合我

时间:2014-06-14 19:41:36

标签: java postgresql jdbc h2

您好我的应用程序访问Postgres数据库,我有许多预定义的查询(排名,分区,复杂的连接等)我对Postgres开火。现在我想用小测试数据对这些查询行为进行单元测试。所以我从H2 / Junit开始。我发现大多数Postgres查询比如Rank,Partition,Complex case等更新等等。所以我想到使用H2 PosgreSQL兼容模式,认为所有postgres查询都适用于H2,如果我错了请纠正我。

我按照H2文档说使用PostgreSQL模式,使用数据库URL jdbc:h2:〜/ test; MODE = PostgreSQL或SQL语句SET MODE PostgreSQL。

我使用SET MODE PostgreSQL启用了模式,我尝试触发其中一个涉及rank()的查询并在postgres中工作,但它不起作用H2。它给了我以下异常

Function "RANK' not found; in SQL statement

请指导我是H2和数据库测试的新手。提前致谢。我正在使用H2 jdbc驱动程序来解决postgres查询,认为H2 Posgress兼容模式将允许我触发postgres查询。

1 个答案:

答案 0 :(得分:32)

  

所以我想到使用H2 PosgreSQL兼容模式,认为所有的postgres查询都适用于H2,如果我错了请纠正我

我担心这不是真的。

H2尝试模拟PostgreSQL语法并支持一些功能和扩展。它永远不会完全匹配PostgreSQL的行为,并且不支持所有功能。

您唯一的选择是:

  • 在测试中使用PostgreSQL;或
  • 停止使用H2不支持的功能

我建议使用Pg进行测试。编写测试工具相对简单,initdb是一个postgres实例并启动它进行测试然后将其撕下来。

根据评论更新:

&#34>之间没有强硬路线。单元"和"整合"试验。在这种情况下,H2也是外部组件。 Purist单元测试将作为测试工具的一部分对查询进行虚拟响应。针对H2的测试同样是对集成"测试对PostgreSQL的测试。它在进程中和内存中是一种便利,但在功能上并不重要。

如果您想单元测试,您应该为您的应用编写另一个数据库目标,以便与您的" PostgreSQL",#34; SybaseIQ"等目标一起使用。称之为" MockDatabase"。这应该只返回查询的预期结果。它并不真正运行查询,它只存在于测试其余代码的行为。

就我个人而言,我认为这是浪费时间,但这就是单元测试纯粹主义者为避免将外部依赖性引入测试工具所做的事情。

如果您坚持对数据库组件进行单元(而不是集成)测试,但无法编写模拟接口,则必须找到使用现有接口的方法。 H2对此来说是一个合理的候选者 - 但是你必须编写一个新的后端,其中包含一组适用于H2的新查询,你不能只重用你的PostgreSQL后端。正如我们已经建立的那样,H2并不支持您使用PostgreSQL所需的所有功能,因此您必须找到使用H2执行相同操作的不同方法。一种选择是使用" expect"创建一个简单的H2数据库。结果和返回这些结果的简单查询,完全忽略了真正的应用程序模式。这里唯一真正的缺点是维持......但这是单位测试的主要痛苦。

就个人而言,我只是用PostgreSQL进行测试。除非我测试单独的类或模块作为窄界面明确定义的单元,否则我不在乎是否有人将其称为“单位”单元。或者"整合"测试。我会对数据验证类进行单元测试。对于数据库接口代码,纯粹单元测试没什么意义,我只是进行集成测试。

虽然有一个进程内存数据库很方便,但并不是必需的。您可以编写测试工具,以便设置代码initdb成为新的PostgreSQL并启动它;然后拆卸代码杀死postmaster并删除datadir。我在this answer中写了更多相关内容。

另见:

至于:

  

如果所有具有预期结束数据集的查询在Postgress中正常工作,我可以假设它在所有其他dbs中都能正常工作

如果我理解你正确说出的话是肯定的,那就是这种情况 - 如果其他代码与PostgreSQL中的数据集配合使用,它通常应该可以与包含来自另一个数据库的相同数据的数据集相同。当然,只要它使用简单数据类型而不是数据库特定功能。