Unit testing 为什么不在单元测试中访问数据库?

Unit testing 为什么不在单元测试中访问数据库?,unit-testing,nunit,Unit Testing,Nunit,我在博客上读到过这样的消息:当单元测试运行时,数据库不应该被击中。我理解这个理论,但是我说我有复杂的存储过程,这是业务域操作的一部分。我想为与业务操作相关的代码编写一组单元测试,但是如果我模拟数据库,我会觉得我并没有“真正”测试操作的所有部分。例如,有人可能会在某个数据库代码中创建一个bug,而测试仍然可以正常运行 我想知道这个关于单元测试的指南在实践中是否是好的。 我见过“集成测试”的概念,但是我不确定使用什么工具来进行集成测试。例如,使用Nunit这样的测试框架创建集成测试可以吗 谢谢 Hu

我在博客上读到过这样的消息:当单元测试运行时,数据库不应该被击中。我理解这个理论,但是我说我有复杂的存储过程,这是业务域操作的一部分。我想为与业务操作相关的代码编写一组单元测试,但是如果我模拟数据库,我会觉得我并没有“真正”测试操作的所有部分。例如,有人可能会在某个数据库代码中创建一个bug,而测试仍然可以正常运行

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

谢谢


Hugo

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

“…当单元测试运行时,不应该命中数据库…”-当然,除非您正在对持久性对象进行单元测试


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

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

  • 你希望你的测试尽快进行
  • 您希望将代码作为单个单元进行测试,而不是测试它如何与其他代码/数据库集成

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

好吧,问题是,如果您让您的单元测试命中数据库,那么您不仅仅是在测试单个代码单元,而是在命中多个代码单元,还有DAL、存储过程等。这就是为什么TDD支持者说不要在单元测试中命中数据库

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


(提示TDD现在反驳…:)

你只是处于语义灰色地带

  • 系统测试从端到端覆盖整个系统
  • 单元测试可用于描述端到端循环的一个子段
在这种情况下,应用程序代码的单元测试将/可能不会命中数据库,但您将/可能有涵盖数据库存储过程的单元测试

基本上,将应用程序划分为一些需要测试的部分,这些部分是有意义的。如果您选择了错误的分区线,那么最终会遇到模拟对象和测试脚手架之类的大代码维护问题

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

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

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

诀窍是只通过API将信息输入和输出到中间集(应用程序层),而不是深入数据库查看是否有什么工作。这样,如果更改数据模式,测试就不会中断

但有时(正如我写这篇文章时实际正在做的那样),您必须查看数据库以生成一个有意义且健壮的测试套件(我正在测试服务器传输协议)

关注如何为应用程序获得最大的代码覆盖率和稳定性,同时编写最少的测试框架,并避免测试套件的脆弱性。

在编写和讨论了人们的答案后,我认为答案可能取决于开发团队中有多少人

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

  • 测试更真实(使用实际数据库)
  • 要编写的测试代码更少(不需要编写数据库的模拟)
使用数据库进行测试的缺点:

  • 在写入数据库访问层之前,测试无法运行
  • 如果有bug或测试失败,您不知道bug是在代码中还是在数据库访问层中
缺点是