2011-09-21 35 views
2

这里的扫描器:如何在没有静态测试数据库的情况下使DAO类的单元测试更加脆弱?

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

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

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

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

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

对这个或其他想法如何管理这种情况的任何反馈将不胜感激。

A.

UPDATE:

至于HSQLDB/H2 /德比的建议,我熟悉他们,但公司还没有准备好,只是还没有走这条路线,零碎做只有一个测试用例不适合。

至于我先前的建议,我想更详细地说明一点 - 考虑这样的场景:

我想确保我的相对复杂的关键字搜索返回的2100次比赛为“约翰·史密斯”。

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

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

回答

5

我同意Andrey和Bedwyr的看法,长期来看最好的方法是创建专门用于测试的hsqldb数据库。如果你没有这个选择,那么你的解决方案看起来是一个合适的解决方案。你不能测试一切,但你也不想测试任何东西。我已经使用这种方法几次来测试Web服务与集成数据库等。但请记住,如果添加新列等,还必须维护此数据库。

您必须决定要尝试的内容去测试。你不想测试hibernate,你不想测试数据库是否提供了你所要求的(用SQL来说)。在你的测试中,你可以假设休眠工作,就像数据库一样。

你说:

我们需要的单元测试是为了确保生成的查询是正确 各种场景。测试它的一种方式 - 可能是 更可取 - 将测试休眠条件创建 通过检查它在最后并嘲笑数据库 交互。然而,这不是理想的,因为它首先是有点作弊(它只是复制代码将做的事情),并且它也不检查标准本身是否导致休眠,以致于无法访问 ,或者当它进入数据库时​​它会导致问题。

为什么要在hibernate barf上给你的标准呢?因为你给它一个错误的标准。这不是hibernate的问题,而是创建条件的代码。你可以在没有数据库的情况下测试。

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

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

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

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

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

+0

非常感谢。是的,对于在正确的级别进行测试,您的观点是绝对正确的,而且我们不在这里测试hibernate或它的标准API。我试图说明,只是测试以某种方式创建标准将是徒劳的,正如您所说的,我们需要测试从标准到结构到数据库的整个链。这正是我所想的,你的评论对此很有帮助!干杯。 –

3

然而,由于历史的原因,没有静态测试数据库(一个代码签入,例如代码的一部分)和我的项目的职权范围不允许我走上创建于

所有你需要做的是激发H2或类似的 - 把一些实体,并执行你的集成测试。一旦您完成了一些测试,您应该能够提取一个数据设置实用程序,该实用程序创建一个包含一些测试数据的模式,如果您觉得需要,可以将其用于所有集成测试。

+0

感谢我的评论@Andrey Adamovich下面。你的建议都是有道理的,但我现在可能无法在现在完成事情的整体结构上做出改变。 –

6

一种方法可以是使用内存数据库像Apache DerbyHSQLDB,并使用DBUnit测试开始前的数据与预填充它。

UPDATE:这是一个不错的article关于这个问题。

+0

谢谢我熟悉hyperSQL db,dbunit和liquibase,并在过去多次使用过它们。但是,这是我目前在我们正在开展的小型项目范围内无法进行的工作。 –

+0

在你的午餐时间,或在一小时前来。在你的机器上启动并运行,然后演示给你的老板,最好是通过测试来发现最近的错误。 – blank

+0

设置hsqldb,创建hibernate配置并添加setUp/tearDown方法来创建空数据库,并指导你的单元测试不应该花太长时间。唯一可能需要更长时间的是创建DBUnit数据集。但是,您可以使用一些真实的数据库从使用DBUnit的数据提取数据,或使用某个数据生成器来创建数据。 –

相关问题