Java H2 postgresql模式似乎不适合我

Java H2 postgresql模式似乎不适合我,java,postgresql,jdbc,h2,Java,Postgresql,Jdbc,H2,我的应用程序访问Postgres数据库,我有许多预定义的查询(排名、分区、复杂连接等),我会对Postgres进行查询。现在我想用小测试数据对这些查询进行单元测试。所以我从H2/JUnit开始。我发现大多数Postgres查询都像秩、分区、更新时的复杂情况等。因此我考虑使用H2 PosgreSQL兼容模式,因为我认为所有Postgres查询都可以在H2上工作。如果我错了,请纠正我 我接着说: 要使用PostgreSQL模式,请使用数据库URL jdbc:h2:~/test;MODE=Postgr

我的应用程序访问Postgres数据库,我有许多预定义的查询(排名、分区、复杂连接等),我会对Postgres进行查询。现在我想用小测试数据对这些查询进行单元测试。所以我从H2/JUnit开始。我发现大多数Postgres查询都像秩、分区、更新时的复杂情况等。因此我考虑使用H2 PosgreSQL兼容模式,因为我认为所有Postgres查询都可以在H2上工作。如果我错了,请纠正我

我接着说:

要使用PostgreSQL模式,请使用数据库URL jdbc:h2:~/test;MODE=PostgreSQL或SQL语句集MODE-PostgreSQL

我使用
SET mode PostgreSQL
启用了模式,并尝试触发一个查询,该查询涉及
rank()
并在Postgres中工作,但不起作用。它给了我以下例外情况:

Function "RANK' not found; in SQL statement
请指导我是H2和数据库测试的新手。提前谢谢。我使用H2 JDBC驱动程序启动Postgres查询,因为我认为H2 Posgres兼容模式将允许我启动Postgres查询

所以我想使用H2 PosgreSQL兼容模式,因为我认为所有postgres查询都可以在H2上运行。如果我错了,请纠正我

恐怕那不是真的

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

您唯一的选择是:

  • 使用PostgreSQL进行测试;或
  • 停止使用H2不支持的功能
我建议使用Pg进行测试。编写一个测试工具(initdb是一个postgres实例)并启动它进行测试,然后将其拆下,这相对简单

根据评论更新:

“单元”测试和“集成”测试之间没有硬性规定。在这种情况下,H2也是一个外部组件。纯粹的单元测试将有一个虚拟的查询响应器作为测试工具的一部分。对H2的测试和对PostgreSQL的测试一样是一种“集成”测试。事实上,它在进程中和内存中是一种方便,但在功能上并不重要

如果您想进行单元测试,您应该为应用程序编写另一个数据库目标,与“PostgreSQL”、“SybaseIQ”等目标一起使用。称之为“MockDatabase”。这应该只返回查询的预期结果。它并不真正运行查询,它的存在只是为了测试其余代码的行为

就我个人而言,我认为这是一种巨大的时间浪费,但这正是一个单元测试纯粹主义者为了避免在测试工具中引入外部依赖所应该做的

如果您坚持对DB组件进行单元(而不是集成)测试,但不能/不会编写模拟接口,那么您必须找到一种使用现有接口的方法。H2将是一个合理的备选方案-但是您必须使用一组适用于H2的新查询编写一个新的后端,您不能仅仅重复使用PostgreSQL后端。正如我们已经确定的那样,H2不支持PostgreSQL所需的所有功能,因此您必须找到不同的方法来处理H2。一种选择是创建一个简单的H2数据库,其中包含“预期”结果和返回这些结果的简单查询,完全忽略实际应用程序的模式。这里唯一真正的缺点是,它可能是一个巨大的痛苦,以维持。。。但这是单元测试

就我个人而言,我只是用PostgreSQL进行测试。除非我在测试单独的类或模块,这些类或模块作为狭窄的接口定义良好的单元,否则我不在乎有人把它称为“单元”或“集成”测试。我将对数据验证类进行单元测试。对于数据库接口代码,纯粹的单元测试毫无意义,我只做集成测试

虽然有一个进程内内存数据库很方便,但它不是必需的。您可以编写测试工具,以便安装代码
initdb
s创建一个新的PostgreSQL并启动它;然后,拆卸代码将杀死邮局主管并删除datadir。我写了更多关于这方面的文章

另见:

至于:

如果所有具有预期最终数据集的查询在Postgress中都可以正常工作,那么我可以假设它在所有其他数据库中都可以正常工作


如果我正确地理解了您的意思,那么是的,就是这样-如果您的其余代码使用PostgreSQL中的数据集,那么它通常应该使用包含来自另一个数据库的相同数据的数据集。当然,只要它使用的是简单的数据类型,而不是特定于数据库的功能。

阅读类似问题的注释,您可能会觉得很有趣。无论如何,我会站在人们一边,主张如果你的应用程序实际使用PostgreSQL,那么你也应该简单地使用PostgreSQL进行测试。Hi@Gord我希望我可以使用Posgres,但作为单元测试的一部分,我应该使用内存数据库,如H2。作为集成测试的一部分,我可以使用Postgres。当你使用数据库时,这不是单元测试……嗨@Craig,谢谢你的回复。我不能停止使用诸如rank()之类的窗口函数,所以你的意思是我不能在postgres兼容模式下使用H2作为rank。大多数内存中的数据库都不支持窗口函数,如果它对您的项目非常重要的话,您可以在H2中实现窗口函数。这不容易也不快。就我个人而言,我建议只在Pg上进行测试。我不清楚为什么不能在单元测试中这样做。当然,这很不方便,但总比不测试你将运行的同一个东西要好。即使我同意你的观点,但人们说我不应该在真实的数据库上做单元测试,比如Postgres,我应该在内存数据库中使用H2来做这件事。如果我像Postgres一样使用真正的db,那将是集成测试而不是单元测试。我对数据库测试还不熟悉,所以有点迷茫?参考/链接?听起来像是BS t