【问题标题】:Unit testing - stubbing an SqlDataReader单元测试 - 存根 SqlDataReader
【发布时间】:2012-04-12 02:39:35
【问题描述】:

我们有一个从 SQL Server 提取数据的 n 层 Web 应用程序。我们的数据访问逻辑返回一个 SqlDataReader,其数据随后用于创建我们的业务对象(也称为数据传输对象)。

我们希望构建单元测试来检查我们的代码,这些代码解释这些 SqlDataReader 对象返回的数据以构建我们的业务对象。

因此,似乎有必要在单元测试期间构建存根来替换 SqlDataReader 对象。可能相当典型的是,我们的 SqlDataReader 对象通常返回多个记录集,每个记录集包含多行。

  1. 这是一项明智的努力吗?
  2. 我们应该如何构建这些存根对象?

在此先感谢

格里夫

【问题讨论】:

    标签: unit-testing nunit sqldatareader stub stub-data-generation


    【解决方案1】:

    自动化测试基本上总是一项明智的努力:)

    能够对此进行测试的第一步是让数据访问逻辑返回 IDataReader 而不是 SqlDataReader - SqlDataReader 实现 IDataReader,所以没有问题。

    在您的单元测试中,您可以手动构建和填充DataTable 对象,并调用dataTable.CreateDataReader() 以获取IDataReader 以传递给被测对象。

    编辑

    要为您的测试提供一组示例数据,我建议您为使用的每个数据表使用ObjectMother,将数据表的创建保存在一个专用位置。然后,您可以将方法放在每个 ObjectMethod 类上,以以强类型的方式更新某些数据。例如:

    public class PersonalDetailsBuilder
    {
        private DataTable _dataTable;
    
        public PersonalDetailsBuilder CreateNewTable()
        {
            this._dataTable = new DataTable("CustomerPersonalDetails")
            {
                Columns = 
                {
                    new DataColumn("CustomerId", typeof(int)),
                    new DataColumn("CustomerName", typeof(string))
                }
            };
    
            return this;
        }
    
        public PersonalDetailsBuilder AddStandardData(int numberOfRows = 3)
        {
            foreach (int i in Enumerable.Range(1, numberOfRows + 1))
            {
                this.AddRow(i, "Customer " + i);
            }
    
            return this;
        }
    
        public PersonalDetailsBuilder AddRow(int customerId, string customerName)
        {
            this._dataTable.Rows.Add(customerId, customerName);
    
            return this;
        }
    
        public IDataReader ToDataReader()
        {
            return this._dataTable.CreateDataReader();
        }
    }
    

    ...然后您可以像这样使用它来获取数据读取器:

    IDataReader customerDetailsReader = new PersonalDetailsBuilder()
        .CreateNewTable()
        .AddStandardData()
        .AddRow(17, "Customer 17")
        .ToDataReader();
    

    【讨论】:

    • 想象我们的 IDataReader 对象之一返回有关客户的详细信息: rs1 = 个人详细信息; rs2 = 权限; rs3 - xxx 等。大多数测试将使用它作为默认数据集。某些测试可能希望使用这些值中的大部分,但会覆盖数据表中的某些属性。这有多容易?几乎像继承......
    • 我不确定我是否理解 - 您是指用于多个结果集的单个数据读取器,还是一组数据读取器?无论如何,我已经更新了我的答案。
    • @DrGriff 你可能想要包含一个重载到AddStandardData,它有一个Action<DataRowCollection> 类型的参数;在您的重载方法中,您将调用原始的AddStandardData 方法,然后执行操作,并传入this._DataTable.Rows 属性。然后,您可以在操作中操作数据表中行的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 2015-04-17
    • 2011-06-20
    • 2012-01-22
    • 2011-09-15
    • 2016-04-25
    • 1970-01-01
    相关资源
    最近更新 更多