去年夏天,我开发了一个基本的ASP.NET/SQL Server CRUD应用程序,单元测试是其中一个要求.当我尝试对数据库进行测试时遇到了一些麻烦.根据我的理解,单元测试应该是:
无国籍
相互独立
可重复的,具有相同的结果,即没有持久的变化
在开发数据库时,这些要求似乎彼此不一致.例如,我无法在不确定要插入的行的情况下测试Insert(),因此我需要先调用Delete().但是,如果他们还没有呢?然后我需要先调用Exists()函数.
我最终的解决方案涉及非常大的设置功能(yuck!)和一个空的测试用例,它将首先运行并指示设置运行没有问题.这是牺牲测试的独立性,同时保持他们的无国籍状态.
我找到的另一个解决方案是将函数调用包装在一个可以轻松回滚的事务中,比如Roy Osherove的XtUnit.这项工作,但它涉及另一个库,另一个依赖,并且对于手头的问题似乎有点太沉重的解决方案.
那么,在面对这种情况时,SO社区做了什么?
tgmdbm说:
您通常使用自己喜欢的自动单元测试框架来执行集成测试,这就是为什么有些人会感到困惑,但他们不遵循相同的规则.您可以参与许多课程的具体实施(因为它们已经过单元测试).您正在测试具体类如何与彼此以及与数据库交互.
因此,如果我正确地阅读此内容,则无法有效地对数据访问层进行单元测试.或者,数据访问层的"单元测试"是否涉及测试,例如,由类生成的SQL /命令,而不依赖于与数据库的实际交互?
除了断言表存在,包含预期的列以及具有适当的约束之外,没有真正的单元测试数据库的方法.但这通常不值得做.
您通常不会对数据库进行单元测试.您通常将数据库纳入集成测试.
您通常使用自己喜欢的自动单元测试框架来执行集成测试,这就是为什么有些人会感到困惑,但他们不遵循相同的规则.您可以参与许多课程的具体实施(因为它们已经过单元测试).您正在测试具体类如何与彼此以及与数据库交互.
DBUnit的
您可以使用此工具在给定时间导出数据库的状态,然后在进行单元测试时,可以在测试开始时自动回滚到其先前的状态.我经常在工作的地方使用它.
单元测试中外部依赖关系的常用解决方案是使用模拟对象 - 也就是说,模仿您正在测试的真实对象的行为的库.这并不总是直截了当,有时需要一些聪明才智,但如果您不想"自己动手",那么.Net有几个好的(免费软件)模拟库.立即想到两个:
Rhino Mocks是一个声誉很好的公司.
NMock是另一个.
还有很多商业模拟库.编写好的单元测试的一部分实际上是为它们设计代码 - 例如,通过使用有意义的接口,这样你就可以通过实现其界面的"假"版本来"模拟"一个依赖对象.可预测的方式,用于测试目的.
在数据库模拟中,这意味着"模拟"您自己的数据库访问层,其中的对象返回组成的表,行或数据集对象,供您的单元测试处理.
在我工作的地方,我们通常从头开始创建自己的模拟库,但这并不意味着你必须这样做.