单元测试如何测试?

时间:2018-07-12 14:37:53

标签: unit-testing testing tdd

我不知道我如何使用单元测试来测试任何东西。

假设我正在测试我的存储库类可以正确地从数据库检索值。正确的方法是实际调用真实数据库并检索并检查这些值。

但是单元测试背后的想法是,它应该孤立地完成,并且连接到正在运行的数据库不是孤立的。因此,通常要做的是模拟 stub 数据库。

但是,为什么要对具有硬编码数据和硬编码返回值的假数据库进行测试,甚至可以测试任何东西?似乎是重言式和浪费时间。

还是我不了解如何正确进行单元测试?

一个偶数测试数据库调用吗?

3 个答案:

答案 0 :(得分:2)

  

我不知道我如何使用单元测试来测试任何东西。

简短的回答:您正在测试逻辑,并忽略了副作用

您不是要测试一切;但是您正在测试某些东西。

此外,如果您牢记您不是真正地测试具有副作用的代码,那么您就有动机去安排代码,以使实际依赖于副作用的部分成为可能。小。大型组件实际上并不关心数据的来源,因为它们很容易测试。

所以“某物”可以是“大多数东西”。

存在 阻抗问题-如果您的测试加倍无法充分体现生产原件,那么您的某些测试结果将不准确。

  

我的理念是尽可能少地测试以达到给定的置信水平

     

Kent Beck, 2008

想象“尽可能少”的一种方法是从成本的角度考虑-我们的目标是给定置信度,因此我们希望使用便宜的单元测试获得尽可能多的置信度,然后用更昂贵的技术弥补差异。

Cory Benfield的演讲Building Protocol Libraries the Right Way描述了我们在此讨论的分离类型的示例。如何解析HTTP消息的逻辑与读取字节的问题是分开的。如果您使复杂的部分易于测试,而使难以测试的部分过于简单而无法失败,那么成功的机会就很大。

答案 1 :(得分:1)

我认为您的关注是正确的。对我来说,TDD不仅仅是单元测试实践,更像是一种进化设计实践,但是我将其保留下来进行另一次讨论。

在您的示例中,我们真正测试的是各个类中包含的逻辑是正确的。通过对来自数据库的数据进行存根处理,您可以控制场景,从而可以确保代码可用于该特定场景。这使确保所有数据方案的完整测试覆盖范围变得更加容易。您是正确的,这确实不是对整个系统进行端到端的测试,但是重点是要降低总体测试维护成本并实现更快的反馈。

我的方法是在单元测试级别模拟大多数协作者,然后在集成测试级别编写验收测试,从而使用真实数据验证您的系统。由于使用带有模拟数据的单元测试可以测试各种数据场景,因此您只需要使用集成测试来测试其中一些场景,就可以确信您的代码将按预期执行。

答案 2 :(得分:0)

您可以单独针对实际数据库测试代码。只需为每个测试创建新的数据库实例,或者一个接一个地同步执行测试,然后在下一个测试之前清理数据库。

但是使用实际数据库会使测试变慢,这会减慢您的工作,因为您需要快速反馈您所做的事情。

不要测试每个类-测试主要功能逻辑,它可以使用许多不同的类,并且仅模拟/存根依赖项,这会使测试变慢。

查找应用程序边界并测试它们之间的逻辑,而无需模拟。
例如,在简单的Web api应用程序中,边界可以是:
 -控制器动作->请求(输入)
 -控制器动作->响应(输出)
 -数据库->收到请求的副作用。

假设我们生活在完美的世界中,新的数据库和Web服务器设置将花费毫秒。然后,您将测试应用程序的整个管道:
1.配置数据库进行测试
2.将请求发送到Web api服务器
3.断言回应中包含预期数据
4.断言数据库状态已按预期更改

但是在当今世界,您的边界将是控制器操作和抽象的数据库访问点。这会使您的测试如下所示:
1.配置模拟数据库访问点(存储库)
2.使用给定参数调用控制器操作
3.断言该操作将返回预期结果
4.可能断言模拟存储库已收到预期的更新参数。

如果您的应用程序没有逻辑,只需从数据库中读取/更新数据-使用实际数据库进行测试,或者,如果您的数据库框架允许,请使用内存中的数据库。