我的应用程序中有一个数据访问层,它包装了一个 ADO.NET 数据提供程序。 DAL 将数据提供程序返回的数据转换为 .NET 对象。我看过很多建议不要对 DAL 进行单元测试的帖子,但令我担心的是,其中可能会出现很多错误 - 有很多循环、强制转换和空值检查。
我有一些关于使用 RhinoMocks 之类的东西创建模拟 DbProvider 的想法,但是在每次测试中我必须模拟的接口(interface)数量会非常多,而且我必须设置的期望数量会使测试很难阅读。似乎每个测试都比它所测试的代码更复杂——从单元测试的 3 个目标的角度来看,这将是一场灾难:
- 可读性
- 可维护性
- 值得信赖
我想实现一个友好的 DbProviderFactory 以从 xml 加载示例数据。我可以在测试中通过依赖注入(inject)将其插入。它应该使维护测试变得更加简单。一个简单的例子可能是:
[TestCase]
public void CanGetCustomer()
{
var expectedCommand = new XmlCommand("sp_get_customer");
expectedCommand.ExpectExecuteDataReader(
resultSet: @"<customer firstName=""Joe"" lastName=""Blogs"" ... />");
var factory = new XmlProviderFactory(expectedCommand);
var dal = new CustomerDal(factory);
Customer customer = dal.GetCustomer();
Assert.IsNotNull(customer, "The customer should never be null");
Assert.AreEqual(
"Joe", customer.FirstName,
"The customer had an unexpected FirstName.");
}
我认为这种方法 - 使用友好的 DbProvider - 可能会更容易测试 DAL 代码。它将具有以下优点:
- 测试数据将在 xml 中,并且可以与单元测试一起放在源代码管理中。它可以在外部文件中,也可以在测试中内联。
- 我没有使用真实的数据库,因此这消除了状态性问题。因此,我不必在每次测试之前将数据库置于已知状态。
- 我不必在每次测试中模拟所有 ADO.NET 接口(interface)。我将编写一组伪造的实现代码,我可以在整个代码库中重复使用它们。
人们可以对这个想法提出一些批评吗?是否已经有类似的实现可供我使用?
谢谢
最佳答案
关于数据访问类(DAL、DAC、DAO、存储库等)的正确单元测试(不,不是集成测试)这一主题,我陷入了很多哲学争论。有些人认为这毫无意义,因为您正在进行集成测试。我发现对这些经常被忽视的代码单元进行单元测试具有巨大的值(value)。首先,为了正确地对数据访问类进行单元测试,它的结构必须正确,并且必须在消费者可能与之交互的沙子上划清界限——想想接口(interface)。数据访问实现应该定义一个接口(interface),它实现了消费应用程序代码仅依赖于该接口(interface)。您选择的基础结构代码(ADO.NET、NHibernate、NDatabase 等)应该具有您的数据访问代码仅依赖的接口(interface)。在这些基础设施接口(interface)(IDBConnection、ISession、IDatabase 等)可用并正确利用后,您可以使用您选择的模拟工具在单元测试中模拟这些接口(interface)。这为您留下了更高质量的数据访问代码,这些代码已经过单元测试(模拟基础设施接口(interface))、集成测试(针对 REAL 数据库),并且具有较低的整体网络耦合。
一个注意事项:在我看来,当数据访问相关代码流过数据访问(或持久性)层时,需要提防一种不好的代码味道。例如,如果您看到连接、命令、 session 等的使用高于数据访问类实现,这就违反了关注点分离。
关于unit-testing - 如何对 DAL 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5651874/