unit-testing - 如何对 DAL 进行单元测试?

标签 unit-testing ado.net mocking dbproviderfactories

我的应用程序中有一个数据访问层,它包装了一个 ADO.NET 数据提供程序。 DAL 将数据提供程序返回的数据转换为 .NET 对象。我看过很多建议不要对 DAL 进行单元测试的帖子,但令我担心的是,其中可能会出现很多错误 - 有很多循环、强制转换和空值检查。

我有一些关于使用 RhinoMocks 之类的东西创建模拟 DbProvider 的想法,但是在每次测试中我必须模拟的接口(interface)数量会非常多,而且我必须设置的期望数量会使测试很难阅读。似乎每个测试都比它所测试的代码更复杂——从单元测试的 3 个目标的角度来看,这将是一场灾难:

  1. 可读性
  2. 可维护性
  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 代码。它将具有以下优点:

  1. 测试数据将在 xml 中,并且可以与单元测试一起放在源代码管理中。它可以在外部文件中,也可以在测试中内联。
  2. 我没有使用真实的数据库,因此这消除了状态性问题。因此,我不必在每次测试之前将数据库置于已知状态。
  3. 我不必在每次测试中模拟所有 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/

相关文章:

unit-testing - 设置 Mobile JUnit 测试以在 JUnit 下运行

java - 如何使用 Mockito 模拟 Java Path API?

reactjs - 我应该测试相反的情况吗?

c# - 如何从 SQL Server 中的存储过程中检索参数列表

java - 如何在每次调用 doReturn 时返回一个新实例?

c# - 在 C# 中模拟局部变量

unit-testing - 无法使用 python 对图像上传进行单元测试

c# - 生成包含标识列的插入语句

c# - SqlConnection 异常 "Invalid column name ' False'

c# - 使用 Moq 验证引用参数的值