在没有静态测试数据库的情况下,如何使DAO类的单元测试变脆? - java

这是scanario:

我正在研究一个DAO对象,该对象使用休眠条件API来形成许多复杂的查询,以对数据库执行某些任务(例如,跨多个字段的关键字搜索)。

我们需要对此进行单元测试,以确保所生成的查询在各种情况下都是正确的。测试它的一种方法(可能是更好的方法)是通过在最后检查休眠条件并模拟数据库交互来正确创建休眠条件。但是,这是不理想的,因为它首先是一种作弊行为(它只是复制代码将要执行的操作),并且它也不会检查条件本身是否导致休眠阻塞或何时进入数据库它会导致问题。

然后使用要使用的选项对测试数据库运行查询。但是,由于历史原因,没有静态测试数据库(例如,将一个代码作为代码的一部分检入的静态数据库),并且我项目的任务不允许我着手创建一个数据库,我们必须满足于针对共享开发数据库,​​该数据库会定期更新生产数据。

当这些刷新发生时,测试背后的数据也可能发生变化,这会使我们的单元测试变得脆弱。我们可以通过在测试中不使用确切的数字来克服它,但这并不是真正足够的测试。

问题是:在这种情况下,人们会做些什么来使测试不那么脆弱?我想到的一个选项是运行执行相同查询的本机SQL(以行为方式-不必与hibernate生成的查询完全相同)以获取期望的数量,然后运行DAO版本以查看如果匹配。这样,可以始终在初始本机SQL中实现查询的行为,并且您将始终拥有正确的数字。

对此问题或其他有关如何处理这种情况的想法的任何反馈将不胜感激。

一个。

更新:

关于hsqldb / h2 / derby的建议,我很熟悉,但是该公司还没有准备好沿这条路线走,只在一个测试用例上零碎地做是不合适的。

关于我先前的建议,我想详细说明一下-考虑以下情况:

我想确保我相对复杂的关键字搜索返回“ John Smith”的2100个匹配项。

为了找到期望的数字,我将分析数据库并使用SQL查询找出数字。将该查询作为测试的一部分有什么弊端,以便使您始终知道自己正在测试条件的行为?

因此,基本上的问题是:如果由于某种原因您无法为测试提供静态数据集,您将如何以一种非脆弱的方式执行集成测试?

参考方案

我同意Andrey和Bedwyr的观点,从长远来看,最好的方法是创建一个专门用于测试的hsqldb数据库。如果您没有这样做的选择,那么您的解决方案似乎是一个合适的解决方案。您无法测试所有内容,但也不想进行任何测试。我已经多次使用这种方法针对集成数据库等测试Web服务。但是请记住,如果添加新列等,则也必须维护该数据库。

您必须决定要测试的内容。您不想测试休眠状态,也不想测试数据库是否提供了您所要求的(就SQL而言)。在测试中,您可以假定休眠和数据库一样有效。

你说:

我们需要对此进行单元测试,以确保生成的查询是
适用于各种情况。一种测试方法-可能是
最好-测试休眠标准是否创建
通过在最后检查它并模拟数据库来正确地进行
相互作用。但是,这是不理想的,因为首先是
作弊(这只是复制代码的作用)和
也不会检查条件本身是否导致冬眠
或者当它进入数据库时​​会引起问题。

为什么应按您指定的条件休眠barf?因为您给它错误的标准。休眠不是问题,而是创建条件的代码。您可以在没有数据库的情况下进行测试。

进入数据库时​​有问题吗?通常,Hibernate会创建适合于条件和您提供的数据库方言的sql,因此,条件仍然存在任何问题。

数据库与休眠期望的不匹配?现在,您正在测试条件和数据库是否对齐。为此,您需要一个数据库。但是,您不再测试标准,而是在测试所有内容是否对齐,这是另一种测试。

因此,实际上,在我看来,您正在进行集成测试,从标准到数据库结构的整个链都有效。这是一个完全有效的测试。

因此,我要做的是在测试中创建与数据库(jdbc)的另一个连接以获取信息。我执行SQL以获取行数等,或检查是否发生了插入。

我认为您的方法是一种完全有效的方法。

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…

Java DefaultSslContextFactory密钥库动态更新 - java

我有一个使用org.restlet.engine.ssl.DefaultSslContextFactory的现有应用程序和一个在服务器启动时加载的密钥库文件。我有另一个应用程序,该应用程序创建必须添加的证书服务器运行时动态地更新到密钥库文件。为此,我在代码中创建了证书和私钥,然后将其写入到目录。该目录由bash脚本监视,该脚本检查是否有新文件,如果出现,它将…