Unit testing 模拟对象与测试数据库

Unit testing 模拟对象与测试数据库,unit-testing,mocking,Unit Testing,Mocking,与具有已知数据的静态测试数据库相比,使用模拟对象的优势是什么?在对数据库进行测试时,使用事务确保没有任何更改。您可以同时执行这两项操作。使用模拟对象测试BLL逻辑,然后使用测试数据库测试DAL逻辑。这样,如果出现故障,您可以很容易地看到测试失败的问题所在。如果您可以确保静态测试数据库在测试期间不会更改,那么我认为静态测试数据库比模拟对象更好。但是,这取决于您想要测试的内容和被测试代码的复杂性。我会选择mock对象,因为与db相比,它们更易于维护。首先,使用mock要比连接到外部数据库快得多。然而

与具有已知数据的静态测试数据库相比,使用模拟对象的优势是什么?在对数据库进行测试时,使用事务确保没有任何更改。

您可以同时执行这两项操作。使用模拟对象测试BLL逻辑,然后使用测试数据库测试DAL逻辑。这样,如果出现故障,您可以很容易地看到测试失败的问题所在。

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

首先,使用mock要比连接到外部数据库快得多。然而,主要原因是mock在每次运行测试时的行为都是相同的,这不能保证使用像数据库这样的外部服务,这意味着单元测试不会随机失败。您还可以轻松地用模拟对象模拟任何类型的故障


对真实的数据库运行集成测试也是一个好主意,但是要测试配置和性能之类的东西。

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

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

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


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

想象一下,您将要编写一个不存在的类。也许是控制器。它不是直接与数据库对话的东西

您很清楚它应该如何运行,并且您知道它应该负责什么,以及它应该将什么委托给其他服务(使用单一责任原则)。因此,您可以编写接口来表示它将要使用的助手类的角色

然后编写一个示例,说明如何使用即将创建的类。如果愿意,可以将该示例称为单元测试。您模拟了与助手类的交互。当您运行这个示例时,它失败了,因为您还没有编写代码。现在,您可以使用helper类的接口编写代码以使其通过—您还没有编写

然后对helper类执行相同的操作,模拟它们的helper

最终您将到达一个与数据库对话的类。或者它与web服务进行通信。或者数据是静态的,或者在内存中。(这与原始类无关,因为您的类与此解耦)

此时,您还需要一个示例来描述此类的行为,如果它是数据库连接器,则需要一个数据库作为示例


以这种方式编写代码可以生成易于使用和理解的代码,而不需要堆栈更高层次的东西所不需要的额外代码。这通常比更容易编写的代码更健壮。这就是为什么我们有时使用mock的原因,因为首先使用mock编写测试有助于产生良好的、可维护的、解耦的设计。

使用db进行测试的设置可能非常困难。如果您发现自己在设置数据库上花费了更多的时间,只是为了测试业务逻辑的某些功能方面,然后,您可能需要使用模拟/假。

有人可能会反对测试数据库不是单元的一部分-test@mathk如果他在存储过程中有逻辑怎么办?@aehiilrs那么使用对象和数据库进行测试仍然是集成测试,而不是单元测试。但不管怎样,这两种测试都是自动化的,并且都可以通过单元测试框架来驱动。现在我的问题是,如果您使用sql编写在数据库上运行的测试来测试数据库(在同一台服务器上)上存储的过程,这是单元测试还是集成测试?措辞:我猜想“BLL逻辑”将展开为“业务逻辑层逻辑”。似乎额外的“逻辑”是多余的。此外,随着“数据访问层”的出现,这些术语在Microsoft产品中普遍使用,因此在回答这个与Microsoft无关的问题时,使用通用术语是有意义的。