如何在没有静态测试数据库的情况下使DAO类的单元测试不那么脆弱



场景如下:

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

我们需要对此进行单元测试,以确保生成的查询对于各种场景都是正确的。测试它的一种方法(这可能是更可取的)是通过在最后检查hibernate标准并模拟数据库交互来测试它是否正确创建。然而,这是不可取的,因为首先它有点作弊(它只是复制代码将要做的事情),而且它也不检查标准本身是否会导致hibernate或当它进入数据库时是否会导致问题。

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

当这些刷新发生时,测试背后的数据也可能发生变化,这将使我们的单元测试变得脆弱。我们可以通过在测试中不使用精确的数字来解决这个问题,但这样做并不是真正充分的测试。

那么问题是:在这种情况下,人们怎么做才能使测试不那么脆弱?我想到的一个选项是运行一个本地SQL,它执行相同的查询(从行为上说——它不必与hibernate生成的查询完全相同)来获得期望的数字,然后运行DAO版本来查看是否匹配。这样,查询的行为可以始终在初始的本地SQL中实现,并且您将始终拥有正确的数字。

对于如何处理这种情况的任何反馈或其他想法将非常感谢。

a .

更新:

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

关于我之前的建议,我想更详细地阐述一下——考虑一下这个场景:

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

为了找到期望的数字,我将分析我的数据库并使用SQL查询找到该数字。将查询作为测试的一部分的缺点是什么,以便您始终知道您正在测试标准的行为?

所以基本上问题是:如果由于某种原因你不能有一个静态的数据集用于测试,你将如何以一种非脆弱的方式执行你的集成测试?

一种方法是使用内存数据库,如Apache Derby或HSQLDB,并在使用DBUnit开始测试之前用数据预先填充它。

UPDATE:这里有一篇很好的关于这个方法的文章

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

你必须决定你要测试什么。您不希望测试hibernate,也不希望测试数据库是否提供了您所要求的内容(就SQL而言)。在您的测试中,您可以假设hibernate正常工作,数据库也正常工作。

你说:

我们需要对此进行单元测试,以确保生成的查询是正确的适用于各种场景。测试它的一种方法是更可取的——是测试是否创建了hibernate标准通过在最后检查它并模拟数据库来正确地交互。然而,这是不可取的,因为首先它有点作弊(它只是复制代码应该做的事情)和此外,它也不会检查标准本身是否会导致hibernate失败或者当它进入数据库时,它会引起问题。

为什么hibernate要根据你给它的标准来运行?因为你给出了错误的标准。这不是hibernate的问题,而是创建标准的代码的问题。你可以在没有数据库的情况下进行测试。

当它到达数据库时有问题吗?一般来说,Hibernate会创建适合于您给它的标准和数据库方言的sql,因此,任何问题都与标准有关。

数据库与hibernate期望的不匹配?现在您正在测试标准和数据库是否一致。为此,需要一个数据库。但是你不再测试标准了,你在测试所有的东西是否对齐,这是一种不同的测试。

所以,实际上,在我看来,你正在做一个集成测试,从标准到数据库结构的整个链条都是有效的。这是一个完全有效的测试。

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

我认为你的方法是完全有效的。

然而,由于历史原因,没有静态测试数据库(例如,代码作为代码的一部分被检入),并且我的项目的权限不允许我开始创建

你所需要做的就是启动H2或类似的东西——在里面放一些实体,然后执行你的集成测试。一旦您为几个测试完成了此操作,您应该能够提取一个数据设置实用程序,该实用程序创建一个包含一些测试数据的模式,如果您觉得有必要,您可以将这些数据用于所有集成测试。

最新更新