我使用许多由后端复杂程度不同的数据库驱动的 Web 应用程序。通常,有一个独立于业务和表示逻辑的ORM层。这使得对业务逻辑进行单元测试相当简单;事物可以在离散的模块中实现,并且测试所需的任何数据都可以通过对象模拟来伪造。
但是测试 ORM 和数据库本身总是充满问题和妥协。
多年来,我尝试了一些策略,但没有一个完全让我满意。
使用已知数据加载测试数据库。针对 ORM 运行测试并确认返回正确的数据。这里的缺点是您的测试数据库必须跟上应用程序数据库中的任何模式更改,并且可能会不同步。它还依赖于人工数据,并且可能不会暴露由于愚蠢的用户输入而发生的错误。最后,如果测试数据库很小,它不会像缺少索引那样显示效率低下。(好吧,最后一个并不是真正应该用于单元测试的,但它并没有什么坏处。)
加载生产数据库的副本并对其进行测试。这里的问题是您可能不知道在任何给定时间生产数据库中有什么。如果数据随时间变化,您的测试可能需要重写。
有人指出,这两种策略都依赖于特定的数据,单元测试应该只测试功能。为此,我看到建议:
您使用了哪些策略来测试数据库驱动的应用程序(如果有的话)?什么对你最有效?
我实际上已经使用了您的第一种方法并取得了相当大的成功,但是我认为以稍微不同的方式可以解决您的一些问题:
将整个架构和用于创建它的脚本保存在源代码管理中,以便任何人都可以在签出后创建当前的数据库架构。此外,将样本数据保存在由构建过程的一部分加载的数据文件中。当您发现导致错误的数据时,将其添加到您的示例数据中以检查错误不会再次出现。
使用持续集成服务器来构建数据库模式、加载示例数据并运行测试。这就是我们保持测试数据库同步的方式(在每次测试运行时重建它)。虽然这要求 CI 服务器有权访问和拥有自己的专用数据库实例,但我说每天构建 3 次我们的 db 模式极大地帮助发现了可能直到交付之前才发现的错误(如果不是稍后)。我不能说我在每次提交之前都重建了架构。有人吗?使用这种方法,您不必这样做(也许我们应该这样做,但如果有人忘记了也没什么大不了的)。
对于我的小组,用户输入是在应用程序级别(而不是数据库)完成的,因此这是通过标准单元测试进行测试的。
加载生产数据库副本: 这是我上一份工作中使用的方法。这是几个问题的巨大痛苦原因:
模拟数据库服务器: 我们目前的工作也是这样做的。每次提交后,我们对注入了模拟数据库访问器的应用程序代码执行单元测试。然后,我们每天执行 3 次上述完整的数据库构建。我绝对推荐这两种方法。