为什么不在单元测试中点击数据库?

时间:2009-06-28 14:08:55

标签: unit-testing nunit

我在博客中读到,在单元测试运行时不应该点击数据库。我理解这个理论,但是说我有复杂的商店程序,它们是业务域操作的一部分。我想为与业务操作相关的代码编写一组单元测试,但是如果我模拟数据库,我感觉我不是“真正”测试操作中的所有部分。例如,有人可能会在其中一个数据库代码中创建一个错误,测试仍然可以正常运行。

我想知道这个关于单元测试的指南是否在实践中很好。 我已经看到了“集成测试”的概念,但我不确定使用什么工具来进行集成测试。例如,是否可以使用像Nunit这样的测试框架创建集成测试?

由于

雨果

7 个答案:

答案 0 :(得分:10)

您只是处于语义灰色区域。

  • 系统测试从端到端覆盖整个系统。
  • 单元测试可用于描述端到端周期的子段。

在这种情况下,您的应用程序代码的单元测试将/可能不会到达数据库,但您可能/可能有/或可能包含数据库存储过程的单元测试......

基本上将您的应用程序划分为有意义的分区中要测试的内容。如果你选择了错误的分区行,你最终会遇到一个带有模拟对象和测试脚手架和东西​​的大代码维护问题......

Web应用程序的一种常见方法是编写一系列测试数据访问层的单元测试......

然后编写一系列测试应用层(包括数据层)的单元测试......

最后写一些基于浏览器的系统测试...

诀窍是只通过API将信息输入和输出中间集 - 应用程序层,而不是挖掘到数据库中以查看是否有效。这样,如果更改数据模式,测试就不会中断。

但有时候(正如我实际上正在编写的那样)你必须调查数据库以制作一个有意义且强大的测试套件(我正在测试服务器 - 服务器传输协议)。

专注于为您的应用程序获得最大代码覆盖率和稳定性的方式,同时编写最少量的测试脚手架,并避免测试套件中的脆弱性。

答案 1 :(得分:4)

单元测试没有激活数据库有两个主要原因:

  • 您希望测试尽可能快
  • 您希望将代码作为一个单元进行测试,而不是将其与其他代码/数据库集成。

在您的情况下,您需要测试存储过程。然后,您需要编写一个运行这些存储过程的测试。您可以通过代码运行它们(集成测试),也可以直接从测试运行它们(单元测试)。在这两种情况下,您都可以使用Nunit。

答案 2 :(得分:2)

嗯,问题是,如果你的单元测试点击数据库,你不是只测试单个代码单元,而是测试几个 - 也就是DAL,存储过程等等。这就是为什么TDD支持者说不要在单元测试中击中数据库。

这也是为什么你不应该在纯粹的,TDD概念化的,理论上神圣的 U nit T 中占很大比重。虽然单元测试本身并不是一件坏事,事实上确保程序员正确构建每个组件非常重要 - 系统测试更为重要。总的来说,找到导致系统测试失败的确切方法可能更难,它们更加真实,并且实际测试系统。 所谓的“组件测试” - 更像是系统测试,但对于系统中只有一小部分,端到端 - 似乎是一个很好的折衷方案。

(现在提示TDD反驳...... :))

答案 3 :(得分:1)

在撰写Should one test internal implementation, or only test public behaviour?并讨论人们的答案后,我认为答案可能取决于开发团队中有多少人。

使用数据库进行测试的优点:

  • 测试更现实(使用实际数据库)
  • 编写较少的测试代码(不需要编写数据库的模拟)

使用数据库进行测试的缺点:

  • 在编写数据库访问层之前,您的测试无法运行
  • 如果出现错误或测试失败,您不知道错误是在您的代码中还是在数据库访问层中

如果(但也许只有)编写上层的人与编写数据库访问层的人不同,这些缺点尤为重要。

答案 4 :(得分:1)

YMHO这里有一些语义问题和一些技术问题。

单元测试应该单独测试一小部分代码,以便在没有其他代码的情况下进行检查。失败的单元测试应该意味着只需要检查一小部分代码(简单地说,实现功能的代码和单元测试本身)。

其他测试范围用于检查整个系统的功能(系统测试),或用于验证完整功能的功能测试,或用于检查交互的集成测试,用于检查已经校正的测试的缺失的回归测试等。

必须为每个项目设计一个测试策略,但通常有不同的类别会有很大帮助。因此,单元测试应限于测试最小的单元代码,并使用其他测试程序来测试功能,集成等。

语义部分是是否正确使用单元测试库来执行某些功能测试,我想如果你将套件分开严格的单元测试和功能测试,这并不是什么大问题(即使他们共享测试工具)

答案 5 :(得分:0)

在测试中处理数据库的问题是数据库中的更改或代码更改可能导致测试失败。单元测试通常应该尽可能直接指向使他失败的变化。 因此,如果要测试数据库访问的代码,可以使用固定的测试数据库。通过这种方式,您可以确定访问数据库的代码是错误的,因为您知道数据库没有更改,如果您想更改数据库设置,请先更改测试数据库并查看测试失败然后修复他然后更改不测试DB。 在我工作的项目中,我们创建了一个小型数据库,在每次测试之前生成内存。

答案 6 :(得分:0)

“......当单元测试运行时,不应该点击数据库......” - 当然,除非你是单元测试持久性对象。

我不知道你引用了哪些博客,但我敢打赌他们所说的是在集成测试期间嘲笑某些组件可能会带来好处。如果您已经对持久层进行了单元测试,则无需再次测试它。在这种情况下,模拟的好处更多地与减少依赖性和不确定性有关。例如,您可能已经对单元进行了单元测试,将其打包,现在是时候将其移动到更接近生产的环境中了。如果您需要的数据库不可用(例如,没有正确的架构版本,缺少您需要的数据,或者只是需要另一个首先到达那里的应用程序),您可以使用模拟来实现集成测试立即进行。

相关问题