2

我使用 QueryDSL 3.2.4 和 Spring Data JPA 1.4.2 作为我的存储库层。我有一个类来获取我的 Web 表单对象(Spring 将搜索表单绑定到的简单 Bean)并为其生成 QueryDSL Criteria 对象,然后将其传递给业务/数据层以运行查询。

我试图找出对这一代 Criteria 对象进行单元测试的最佳方法。根据要搜索的内容,查询中将包含不同的字段组合(基本上,典型的搜索表单,其中字段可以为空白以不基于它进行约束,但每个非空白字段表示一个搜索条件,并且一些字段可能有一些额外的选项,例如它是用于“精确匹配”、“开始于”还是“包含”。)

有一个Spring Data JPA 教程它提倡在 JPA Criteria API 上使用 QueryDSL,部分原因是可以通过比较 .toString() 来对 QueryDSL 进行单元测试。所以,这就是我现在倾向于的方式,确保生成的 Criteria 对象的 toString() 对于我正在尝试测试的查询是合理的,但我不确定如何获得“预期" toString 没有提前构建所需的查询并查看它的 toString 是什么,所以感觉不是一个很好的测试,而且感觉它是基于 QueryDSL 的内部结构,可能会发生变化。(我认为大多数类上的 toString 主要是一种调试辅助工具,而不是规范的一部分,尽管如果有人向我指出关于 QueryDSL 如何创建其 toString() 方法的规范,并且它是使用方式的一部分和/或测试库的使用情况,

还有另一个 StackOverflow 问题“如何在给定方法中对 querydsl 查询进行单元测试? ”,但这看起来是关于测试整个查询并需要一个模拟 EntityManager。我希望只测试 Criteria 部分,所以我希望有比这更简单的方法,我需要模拟一个使用 Criteria 的查询,然后模拟一个 EntityManager 来使用它,所有看起来对我来说,这比我为正确创建 Criteria 对象所做的单元测试要复杂得多。

我觉得我不能成为唯一一个试图测试我正在创建正确标准的人。感谢您对我做错了什么或如何更好地进行单元测试的任何见解。

4

2 回答 2

3

我的方法是从简单的查询开始,然后收集越来越复杂的“样本”。是的,我正在使用实际的查询结果,并在expected观察后将其复制到我的单元测试部分中。

这不是一个很好的测试。目的略有不同:它记录了您的期望。

当某些事情发生变化时,您的测试将开始失败,您可以在“我昨天的预期”和“我今天得到的”之间创建差异。

这也记录了您的代码能够做什么。当发现生产中的错误时,您可以尝试编写新的单元测试并查看有多少其他错误也失败了。这使您可以很好地了解更改的影响(1 个更改 + 90% 的测试失败?您发现了一个热点!)

当我修复错误时,我开始看到通常会出错的模式,我可以通过特定的单元测试来保护这些地方(比如在大型查询构建器使用的子构建器中)。

对于一些复杂的查询,我创建了单元测试以查看它们是否真的有效。这让我相信快速的“字符串比较”单元测试是有效的。

于 2013-11-13T17:33:01.237 回答
3

我使用真实的 EntityManager 和真实的内存H2 数据库对我的所有 QueryDSL 代码进行“单元”测试。没有模拟 EntityManager 也没有检查生成的 JPQL,我测试查询实际上返回了我期望的对象。

单元测试的纯粹主义者可能会争辩说这不是一个真正的单元测试,但我的代码可以工作并且足够快。

这可以通过 springs嵌入式数据库支持轻松实现:

<jdbc:initialize-database data-source="dataSource">
  <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/>
</jdbc:initialize-database>
于 2013-11-13T17:53:55.630 回答