如何对数据访问层进行单元测试?

3
我在我的应用程序中有一个数据访问层,它包装了一个 ADO.NET 数据提供程序。DAL 将数据提供程序返回的数据转换为 .NET 对象。我看到很多帖子建议不要对 DAL 进行单元测试,但是这让我担心,在其中可能会出现很多问题——有很多循环、强制类型转换和空值检查。
我考虑过使用 RhinoMocks 创建模拟 DbProvider,但是每个测试中需要模拟的接口数量太多,而且需要设置的期望数会使测试非常难以阅读。似乎每个测试都比它所测试的代码更加复杂——这从单元测试的三个目标的角度来看是一场灾难:
1. 可读性 2. 可维护性 3. 可信度
我想到了实现一个友好的 DbProviderFactory 以从 xml 中加载示例数据。我可以通过依赖注入将其插入到测试中。这应该能够使测试更加简单易于维护。一个微不足道的例子可能是:
[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接口。我将编写一组虚假实现,可在整个代码库中重复使用。
人们能否对这个想法提出一些批评?是否已经有类似的实现可以用于此?
谢谢
1个回答

2
我经常就数据访问类(DALs、DACs、DAOs、Repositories等)的适当单元测试问题(不是集成测试)进行哲学辩论。有人认为这是无意义的,因为你正在进行集成测试。我发现单元测试这些经常被忽视的代码单元非常有价值。首先,为了正确地单元测试数据访问类,它必须被正确地构建,必须划定界限,以便消费者可以交互 - 考虑接口。数据访问实现应该定义一个接口来实现,消费应用程序代码只有依赖关系。您选择的基础架构代码(ADO.NET、NHibernate、NDatabase等)应该有界面,您的数据访问代码只有依赖关系。使用这些基础架构接口(IDBConnection、ISession、IDatabase等)并正确利用它们,您可以使用您选择的模拟工具在单元测试中模拟这些接口。这使您得到更高质量的数据访问代码,该代码已经过单元测试(模拟基础架构接口)、集成测试(针对真实数据库)和更低的净耦合。
注意:在我看来,要警惕的一个坏代码气味是当与数据访问相关的代码泄漏到数据访问(或持久化)层之外时。例如,如果您看到连接、命令、会话等在数据访问类实现之上使用,这表明违反了关注点分离。

3
我同意你所说的一切。但是挑战在于测试与ADO.NET IDbProvider实现交互的代码。我想验证代码能够正确处理null值、空结果集或异常情况。我不想注入更多的抽象层,因为那只会把问题转移到其他地方。模拟ADO.NET很复杂,因为使用了很多实体。 - sheikhjabootie

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