测试依赖于数据库的代码的更好做法是什么?模拟和存根?还是种子数据?



似乎我一直读到,在测试时,使用模拟数据库对象或存储库。没有理由去测试别人的数据库代码,对吧?没有必要让代码与数据库中的数据混淆,对吧?

最近我看到了一些测试,这些测试设置了一个数据库(可能在内存中),并用测试数据播种它,只是为了运行测试。

一种方法比另一种方法好吗?如果使用种子数据的测试值得运行,那么是否应该使用模拟数据库连接呢?如果是,为什么?

有很多方法可以测试与数据库交互的代码。

存储库模式是在数据访问代码上创建facade的一种方法。它使在测试期间存根/模拟存储库变得容易。这在需要单独测试一段业务逻辑时非常有用,并且虚拟值可以帮助测试代码的不同分支。

假数据库(内存或本地文件)不太常见,因为需要一些知道如何从真实数据库和假数据库读取数据的"中间件"。通常,在整个系统中使用一个存储库并模拟存储库是有意义的。这种方法在一些已有基础设施的旧系统中更为可行。例如,您使用一个真实的数据库,然后出于测试性能的原因切换到一个假数据库。

另一种选择是使用一个实际的数据库,用虚假数据填充它。这种方法比较慢,并且需要编写大量脚本。然而,作为集成测试的一部分,这种方法是相当常见的。我曾经编写过很多"事务性"测试,在这些测试中,我在运行测试后使用数据库事务回滚更改。我将编写一个大型测试,在一个特定的表上执行所有CRUD操作。

当您测试将SQL结果转换为对象的代码时,最后一种方法是有意义的。您的SQL可能无效(或者您使用了错误的存储过程名称)。当映射到对象时,也很容易忘记检查空值,执行无效的强制类型转换等。这段代码应该在某个时候进行测试。ORM可以帮助减轻很多这样的测试。

这些天我特别懒。我使用存储库。我的大多数数据层代码在执行实际集成测试(使用虚拟数据访问真实数据库)时都会被触及,因此我不需要测试单个数据库调用(不再需要事务性测试)。我还使用orm来执行大多数SELECT语句。我认为许多行业正在朝着这种更懒惰的方式发展。

你应该两者并用。

业务服务应该依赖于dao,并通过模拟dao进行测试。这允许快速,易于实现,易于维护的测试。

dao的唯一职责是包含数据库访问代码(查询等),也应该进行测试。所以你应该使用一个测试数据库,使用测试数据,并检查他们的查询返回/保存他们支持返回/保存的内容。

我不太喜欢使用内存数据库,这与生产中使用的数据库不同。某些查询、约束等的行为会因数据库而异,您最好确保代码将在生产数据库上工作,而不是在仅供测试使用的内存数据库中工作。