有没有不适合 java/scala 的类似 dbunit 的框架?

Posted

技术标签:

【中文标题】有没有不适合 java/scala 的类似 dbunit 的框架?【英文标题】:Is there a dbunit-like framework that doesn't suck for java/scala? 【发布时间】:2011-04-26 09:16:58 【问题描述】:

我正在考虑制作一个新的轻量级数据库填充框架。我绝对讨厌 dbunit。在此之前,我想知道是否有人已经这样做了。

我不喜欢 dbunit 的地方:

1) 不推荐使用最简单的编写和入门格式。他们希望您使用臃肿的格式。有些甚至需要 xml 模式。是的,随便。

2) 它们不是按照您编写它们的顺序填充行,而是按照在 xml 文件中定义的顺序来填充行。这真的很糟糕,因为您不能以外键约束不会导致问题的方式对数据进行排序。这只会迫使您经历完全关闭它们的麻烦。

这也会浪费时间并使您的 junit 基类膨胀以包含禁用外键约束的代码。您可能必须测试数据库类型(hsqldb 等)并以特定于数据库的方式禁用它们。这太糟糕了。

如果 dbunit 帮助自动禁用外键约束作为其框架的一部分,可能会更好,但他们不这样做。他们确实跟踪方言......那么为什么不使用它们呢?最终,所有这一切都会迫使程序员浪费时间而不是快速起床并进行测试。

3) XML 写起来很痛苦。关于这一点我不需要多说。他们还提供了很多方法来做到这一点,我认为这只会使事情复杂化。只需提供一种真正可靠的方法并完成它。

4) 当您的数据变大时,跟踪 id 及其一致/正确的关系是一件非常痛苦的事情。

另外,如果你一个月没有从事一个项目,你如何记住 user_id 1 是管理员,user_id 2 是业务用户,user_id 3 是工程师,而 user_id 4 是别的什么?回去检查这会浪费更多时间。除了任意数字之外,应该有一种有意义的方式来检索它。

5) 速度很慢。我发现除非使用 hsqldb,否则它会非常缓慢。它不一定是。还有很多方法可以弄乱它的配置,因为“开箱即用”并不容易。您必须经历一个驼峰才能使其正常工作。所有这些都是鼓励人们不要使用它,或者当他们开始使用它时会生气。

6) 一些值往往会重复很多,比如日期。最好指定默认值,甚至让框架自动放入默认值,即使您没有告诉它在其中放入默认值。这样你就可以只用你想要的值来创建对象,剩下的就不用了。如果不需要,这肯定优于指定列的每个角落和缝隙。

7) 最烦人的可能是第一个条目必须包含所有值 - 甚至是空占位符 - 否则未来的行将不会选择您实际指定的列。

DBunit 也没有将 [NULL] 转换为真正的空值的合理默认值。您必须手动添加它。告诉我,谁没有用 dbunit 做过这个?每个人都有。不应该是这样的!

这意味着如果你有一个多态对象,你必须在第一行中声明每个子类的连接表的所有外键,即使它们是空的。如果您为所有子类模式创建一个表,您仍然必须在第一行指定所有字段。这太可怕了。

有什么能让我满意的,还是我应该成为下一个更好的数据库测试框架的框架开发者?

【问题讨论】:

而不是写一个新的只是修复损坏的东西...... 我想在 scala 中做它并考虑向后兼容性,因为这几乎是未来的方式。 【参考方案1】:

我不知道有任何 DbUnit 的真正替代品,@Joe 提到的工具都没有出现在我眼中:

Incanto: 不是数据库不可知论者 SQLUnit:用于测试数据库存储过程的回归和单元测试工具(这不是 DbUnit 的意义所在) Cactus:容器内测试工具(我看不出它对数据库有什么帮助) Liquibase:数据库迁移工具(不加载/验证数据) ORMUnit: 可以初始化一个数据库,仅此而已 JMock: 根本不与 DbUnit 竞争

话虽如此,我个人已经在小型和大型项目中成功使用过 DbUnit 多次,我发现它非常有用,尤其是在使用 Unitils 及其 DbUnit 模块时。这并不意味着它是完美的并且无法改进,但使用不错的工具(无论是定制的还是 Unitils 之类的),使用它是一种不错的体验。

所以让我回答你的一些观点:

    不推荐使用最简单的编写和入门格式。他们希望您使用臃肿的格式。有些甚至需要 xml 模式。是的,随便。

DbUnit 支持平面或结构化 XML、XLS、CSV。您想使用哪种革命性格式?顺便说一句,使用 XML 时,DTD 或模式不是必需的。但是它给了你很好的东西,比如验证和自动完成,那有什么不好? Unitils 可以为您轻松生成它,请参阅Generate an XSD or DTD of the database structure。

如果 dbunit 帮助自动禁用外键约束作为其框架的一部分,可能会更好,但他们不这样做。他们确实跟踪方言......那么为什么不使用它们呢?最终,所有这一切都会迫使程序员浪费时间而不是快速起床并进行测试。

他们正在等待你的补丁。

同时,Unitils 支持透明地处理约束,请参阅Disabling constraints and updating sequences。

    XML 写起来很麻烦。关于这一点我不需要多说。他们还提供了很多方法来做到这一点,我认为这只会使事情复杂化。只需提供一种真正可靠的方法并完成它。

我猜痛苦是主观的,但我不觉得痛苦,尤其是在使用模式和自动完成时。你建议的灵丹妙药是什么?

    当您的数据变大时,跟踪 id 及其一致/正确的关系是一件非常痛苦的事情。

让它们保持小,这是一个知道best practice。你违背了一个已知的最佳实践,然后抱怨......

另外,如果你一个月没有从事一个项目,你如何记住 user_id 1 是管理员,user_id 2 是业务用户,user_id 3 是工程师,而 user_id 4 是别的什么?回去检查这会浪费更多时间。除了任意数字之外,应该有一种有意义的方式来检索它。

是的,任务切换会适得其反。但是由于您使用的是低级别数据,因此您必须知道它们是如何表示的,除非您使用更高级别的 API,否则没有神奇的解决方案当然(但这不是 DbUnit 的目的)。

    速度很慢。我发现除非使用 hsqldb,否则它会非常缓慢。它不一定是。还有很多方法可以弄乱它的配置,因为“开箱即用”并不容易。您必须经历一个驼峰才能使其正常工作。所有这些都是鼓励人们不要使用它,或者当他们开始使用它时会生气。

这是数据库和 JDBC 所固有的,而不是 DbUnit。如果您希望事情尽可能快,请使用像 H2 这样的快速数据库(如果您有更好的不可知论方法来做事,我很乐意了解它)。

    最烦人的可能是第一个条目必须包含所有值 - 甚至是空占位符 - 否则以后的行将不会选择您实际指定的列。

在使用 Unitils - Home - JavaPolis 2008 或 Unit testing: unitils & dbmaintain 等演示文稿中提到的 Unitils 时不会。

有什么能让我满意的,还是我应该成为下一个更好的数据库测试框架的框架开发者?

如果您认为自己可以让事情变得更好,也许可以为现有的解决方案做出贡献。如果那是不可能的,并且如果你认为你可以创建杀手级数据库测试框架,我能说什么,去做吧。但不要忘记,咆哮很容易,使用自己的解决方案想出解决方案就不那么容易了。

【讨论】:

最后一段好智慧。 不容易,不代表做不到或者我做不到。我很聪明,也很努力。谢谢你的帖子。你写的所有东西都应该得到 +rep ;) 哦,我从来没有遇到过没有架构的自动完成问题。给定 1 个没有模式的标签示例,IntelliJ Idea 自动完成就好了。架构最终变得臃肿,因为我必须在修改我的域模型和休眠配置的同时修改架构。在这个过程中添加“只是一件事情”是不好的,并且获得一个伪装它的工具不是一个真正的解决方案:/ 我只是想说,咆哮并不是我所做的全部。访问此处查看 scaladbtest,它修复了我“咆哮”的所有内容:github.com/egervari/scaladbtest @egervari 感谢您的工作和分享,肯,我尊重这一点。好工作。竞争很好,我会试试 scaladbtest 看看感觉如何 :)【参考方案2】:

作为一名 DbUnit 开发人员,我很感激批评,我必须部分同意你的看法。我们目前正在开始设计下一个 DbUnit 主要版本,我希望邀请您参与讨论和开发。

我不会回答您的问题,因为您的问题与 DbUnit 并没有真正的关系,而是与 DbUnit 的替代品有关。无论如何,我只想强调您的第 7 点是完全错误的:您不再需要指定第一行的所有列,该功能称为列感应。我不会告诉你为什么默认不启用它,因为你肯定足够聪明,可以自己理解它。

我会给scaladbtest一个深入的检查,希望我们能整合他们的想法。

【讨论】:

我已经深入研究了你的 scaladbtest 项目,我不得不承认它是一个很好的扩展,但是你在将它与 dbUnit 进行比较时付出了太多努力。实际上你只支持一种文件格式,你还没有处理过很多 dbUnit 能够自动解决的问题。我可以建议跟随 dbUnit 的演变吗?下一个 dbUnit 版本对您来说将非常有趣。 Adn 我们热爱竞争,所以请继续推动我们做到最好,我们也会这样做;)【参考方案3】:

面对使用 DBUnit 的类似问题,我发现:http://dbsetup.ninja-squad.com/index.html 可能会解决问题。例如,所有 DB 内容都包含在 java 类本身中,而不是在单独的文件中表示测试数据。

【讨论】:

这太棒了。我正在考虑从现在开始使用它而不是 DbUnit。 +1,我发现DbSetup 使用起来最方便。【参考方案4】:

如果您使用 Spring 框架(或者至少不介意将其用于测试),那么 Spring DBUnit 是目前我所知道和使用的普通 DBUnit 的最佳(维护)替代方案。引用他们的网站:

Spring DBUnit 提供了 Spring 测试之间的集成 框架和流行的 DBUnit 项目。它允许您设置和 使用简单的注释和检查来拆解数据库表 测试完成后预期的表格内容。

Spring DBUnit 似乎是用于 DB 单元测试的“有点官方”的 Spring 解决方案(使用 DBUnit);至少图书馆的作者/维护者 Phil Webb 正在 SpringSource/Pivotal 工作。

【讨论】:

我很失望@DatabaseSetup 不能从父类继承。看来项目现在维护得不好。【参考方案5】:

我使用 DBUnit,并使用一些包装器来平滑粗糙的边缘。一个可以补充或重叠功能的好工具是Jailer。它可以从参考数据库中提取数据子集,并将其存储为与 DBUnit 兼容的 XML 文件或“拓扑排序的 DML 文件”,这些文件尊重外键约束。

【讨论】:

【参考方案6】:

我刚刚发布了一个名为 JDBDT(Java 数据库增量测试)的库,它 您可以在软件测试中用于数据库设置和验证。

看看http://jdbdt.org

最好, 爱德华多

【讨论】:

刚刚检查了您的库 JDBDT。干得好!我喜欢。与 DBUnit 相比,它有很多优点,我认为它很快就会成为现实 谢谢,很高兴你喜欢它。试一试,通过 GitHub 问题跟踪器让我知道任何问题。 GitHub上有一个教程-jdbdt.org/Tutorial.html和相关代码。【参考方案7】:

你说得很好。

在过去的几年里,我一直在为许多门户网站工作,主要是使用 php,但偶尔也会使用一些 Java。 和你一样,我不明白这些年来框架和单元测试开发人员似乎没有意识到在过去十年中存储处理发生了多少变化。 仅仅将创建/插入/截断语句发送到某个数据库是不够的! 如果您在大规模运营,您最终会使用各种存储后端,分层组织以快速推出热门内容。另外在数据库方面还有数据分区的问题。如果您没有提供适当的外键抽象,那么当您的存储设置发生更改时,您肯定会发疯。虽然我们正在这样做:按外键优先级排序的夹具有很多陷阱,我还没有看到DBUnit 的真正解决方案。

无论如何,关键在于仅用于单元测试的基本数据库存储对于复杂的存储设置是不够的,因为它们通常无法在实时环境中重现问题并且维护起来很麻烦。

不想让自己听起来像个粉丝:ruby on rails 是一个不错的地方。 这有一个持久的模型概念,人们似乎实际上已经投入了一些思考。如果您在PHP 交易,Symfony 是您的理想去处。它受到默认包含 Doctrine 的限制,它也非常以 DB 为中心,但它具有干净的接口和出色的可扩展性,并且完全复制了 rails 夹具系统。从专业上讲,我现在需要坚持使用自制解决方案,但它们工作正常。

【讨论】:

【参考方案8】:

又一次投票支持使用现代库包装 DBUnit 以提高可用性和简洁性。我的选择是database-rider,它使 DBUnit 易于使用,甚至支持 JUnit 5,如下例所示:

@RunWith(JUnitPlatform.class)
@ExtendWith(DBUnitExtension.class)
@DBUnit(cacheConnection = true, cacheTableNames = true)
class TestInstrumentQueryService 

    private ConnectionHolder connHolder = () -> EntityManagerProvider.instance("my-jta-unit").connection();

    @DBRider
    @DataSet("datasets/instrumentIds.yml")
    void testFindInstrumentById() 

        InstrumentQueryService iqs = new InstrumentQueryService(EntityManagerProvider.em());

        Instrument instr = iqs.findInstrumentById(InstrumentIdType.TICKER_BBG, "AAPL");
        assertEquals(100, instr.getId());
    

注意这如何允许无缝地利用(简洁的)YAML 测试数据集(YAML 不是 XML,尽管我相信 DBUnit 实际上原生支持这些数据集)。

【讨论】:

【参考方案9】:

这里有一些我特别喜欢或觉得有趣的工具(DBunit 除外)的简短列表。至少他们可能会提供一些灵感:

Incanto SQLunit Cactus Liquibase ORMUnit JMock

请注意,就范围或功能集而言,这些都不是 DBunit 的真正竞争对手。但是,那里有一些有趣的想法可能值得一看。祝你好运!

【讨论】:

【参考方案10】:

我们正在编写 Daleq 作为 DbUnit 的包装器,以解决上述一些问题。它允许仅在您的单元测试中填充数据库,而不是依赖于编辑 XML 文件。

【讨论】:

【参考方案11】:

DBUnit 也有类似的问题。特别是使用它来填充本地开发数据和从真实数据库中导出数据。我遇到了几种情况,它会导出一个无法导入的数据集。

这启发了我为它编写一个新库:https://github.com/jeffskj/phonydata

这使用了一个 groovy DSL 来定义数据集,这使得数据的表示非常紧凑,并且可以做一些很酷的事情,比如生成随机数据,因为它只是一个 groovy 代码。

【讨论】:

【参考方案12】:

DBUnit 的情况有时确实令人沮丧。一些问题从Marc Philipp 和dbunit-datasetbuilder 解决,特别是如果你将它与validator 结合使用,这还处于非常早期的阶段。您可以在 SZE 看到它的实际效果。

免责声明:所有引用的 github 资源均由我维护。

【讨论】:

【参考方案13】:

可以找到使用 Spring 配置和 Specs2 测试的替代方法here

【讨论】:

【参考方案14】:

我刚刚发布了一个基于 DSL 的通用框架,称为踏板加载器,可通过github 获得。文档here。

它允许您直接使用 JPA 实体级抽象。由于它是一个 groovy 脚本,因此您可以使用所有 groovy 结构。

要将行插入到由名为 Student 的 JPA 实体支持的表中,其中包含名为 id、name 和grade 的字段(不是数据库列,而是映射的字段),您可以执行以下操作:

allStudents = table(Student, ['id', 'name', 'grade']) 
    row 1, 'Joe', Grade.A
    rowOfInterest = row 2, 'John', Grade.B

Grade 是 Student 类中的一个枚举,它映射到数据库列(可能使用 JPA 2.1 @Convert 注释)。 allStudents 是一个包含行的列表,而 rowOfInterest 是对特定行的引用。这些属性(allStudents 和 rowOfInterest)可用于您的单元测试。

【讨论】:

以上是关于有没有不适合 java/scala 的类似 dbunit 的框架?的主要内容,如果未能解决你的问题,请参考以下文章

Spark 中用 Scala 和 java 开发有啥区别

Drupal dbu查询示例

dbm、dbu、dbv之间是怎么换算的?dbv和mv呢?

FileDialog文件过滤

dbu query PHP函数,用于使用ADOdb库进行ddbb查询

dbu query PHP函数,用于使用ADOdb库进行ddbb查询(插入查询)