模拟对象与测试数据库的区别

11

使用模拟对象相对于使用已知数据的静态测试数据库并使用事务确保在针对数据库进行测试时没有更改的优点是什么?

使用模拟对象的优点是可以更加轻松地模拟测试场景并且可以避免对真实数据库的依赖。这意味着测试可以更快地运行而且更加独立。使用静态测试数据库和事务需要额外的设置和处理,并且需要更长的时间来执行测试。

1
有人可能会反对测试数据库不属于单元测试的一部分。 - mathk
@mathk 如果他的存储过程中有逻辑呢? - aehiilrs
@aehiilrs 然后使用对象和数据库进行测试仍然是集成测试,而不是单元测试。但两者都是自动化测试,并且都可以使用单元测试框架进行驱动。现在我的问题是,如果您编写在数据库上运行的 SQL 测试来测试数据库上的存储过程(在同一服务器上),那么这是单元测试还是集成测试? - jyoungdev
6个回答

13

你可以同时进行这两种测试。使用模拟对象来测试业务逻辑层(BLL)的代码,然后使用测试数据库来测试数据访问层(DAL)的代码。这样,如果出现问题,你可以轻松地通过测试失败的位置看出问题所在。


4
我猜"BLL logic"应该是指"业务逻辑层"。似乎多余地再加上一个"逻辑"。此外,"数据访问层"和它们一起被广泛地用在微软产品中,因此在回答与微软无关的问题时最好使用常见的术语。 - n611x007

6
首先,使用模拟对象比连接外部数据库更快。然而,主要原因是模拟对象每次运行测试时的行为都是相同的,而这在像数据库这样的外部服务中无法保证,这意味着单元测试不会随机失败。您还可以使用模拟对象轻松模拟需要处理的任何类型的故障。
对于测试配置和性能等方面,运行集成测试以针对真实数据库也是一个好主意。

2
如果您可以确保静态测试数据库在测试过程中不会更改,那么我认为静态测试数据库比模拟对象更好。但是,这取决于您想要测试什么以及被测试代码的复杂性。与数据库相比,我会选择模拟对象,因为它们更容易维护。

2
想象一下,你要编写一个还不存在的类。也许它是一个控制器,不会直接与数据库交互。
你已经很好地了解它应该如何运作,知道它应该负责什么,以及应该委托给某些其他服务(使用单一职责原则)。因此,你编写了接口来表示它将使用的辅助类的角色。
然后,你编写了一个关于如何使用即将创建的类的示例。如果你愿意,你可以称之为单元测试。你模拟了与帮助类的交互。当你运行示例时,它会失败,因为你还没有编写代码。现在,你可以编写代码使其通过,使用辅助类的接口 - 你还没有编写这些接口。
然后你用同样的方式处理辅助类,模拟出它们的辅助程序。
最终,你会到达一个与数据库交互的类。或者它可能与Web服务交互。或者数据是静态的,或者在内存中。(对于原始类来说,这并不重要,因为你的类与此解耦)。
在这一点上,你需要一个描述这个类行为的示例,如果它是一个数据库连接器,你需要一个数据库来进行示例。
以这种方式编写代码会产生易于使用和理解的代码,没有任何不需要在堆栈上方使用的额外内容。这通常比编写更容易的代码更加健壮。这就是为什么我们有时使用模拟 - 因为使用模拟编写测试可以帮助产生良好,可维护和解耦的设计。

1

通常你会同时使用这两种方法。

对于单元测试,您将使用模拟对象。这样,您可以以更细粒度的方式测试系统,因为您可以模拟每个对象 - 不仅是包装数据库连接的对象。一般来说,最好将每个类与所有依赖项分开进行单元测试。好处是 - 可以在所有级别上测试所有错误处理并确保测试所有代码路径,当您获得测试失败时,可以立即找到原因等。

对于集成和端到端测试,您将测试系统的大部分或整个系统。然后,您将连接到数据库(因为此连接是测试的一部分)。显然,您必须确保数据库处于已知状态等等。

您最终将拥有比集成测试更多的单元测试,因此使它们非常快速实际上非常重要 - 这是使用模拟对象的另一个优点。


0

使用数据库进行测试的设置可能很繁琐。如果你发现自己花费更多时间来设置数据库,只是为了测试业务逻辑的某些功能方面,那么你可能想要使用模拟/虚假数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接