单元测试 - 存根 SqlDataReader
Posted
技术标签:
【中文标题】单元测试 - 存根 SqlDataReader【英文标题】:Unit testing - stubbing an SqlDataReader 【发布时间】:2012-04-12 02:39:35 【问题描述】:我们有一个从 SQL Server 提取数据的 n 层 Web 应用程序。我们的数据访问逻辑返回一个 SqlDataReader,其数据随后用于创建我们的业务对象(也称为数据传输对象)。
我们希望构建单元测试来检查我们的代码,这些代码解释这些 SqlDataReader 对象返回的数据以构建我们的业务对象。
因此,似乎有必要在单元测试期间构建存根来替换 SqlDataReader 对象。可能相当典型的是,我们的 SqlDataReader 对象通常返回多个记录集,每个记录集包含多行。
-
这是一项明智的努力吗?
我们应该如何构建这些存根对象?
在此先感谢
格里夫
【问题讨论】:
【参考方案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
属性。然后,您可以在操作中操作数据表中行的内容。以上是关于单元测试 - 存根 SqlDataReader的主要内容,如果未能解决你的问题,请参考以下文章