使用Moq模拟IDbDataAdapter填充方法

时间:2011-08-16 16:59:02

标签: unit-testing mocking nunit moq

我有一个使用Excel文件读取数据的对象,该对象需要IDbConnectionIDbDataAdapterIDbCommand。我使用适配器填充方法用数据填充表,这就是我目前正在嘲笑它的方式:

[TestCase]
public void TestReadCellsFromSpreadsheetReadsSuccessfully()
{
    var cells = new List<ReportData>
                    {
                        new ReportData { CellId = 1, ExcelCellLocation = "A1"},
                        new ReportData { CellId = 2, ExcelCellLocation = "A2"},
                        new ReportData { CellId = 3, ExcelCellLocation = "A3"},
                        new ReportData { CellId = 4, ExcelCellLocation = "A4"}
                    };

    _mockAdapter.Setup(a => a.Fill(It.IsAny<DataSet>()))
        .Callback((DataSet ds) =>
                      {
                          if (ds.Tables["Table"] == null)
                          {
                              ds.Tables.Add("Table");
                              ds.Tables["Table"].Columns.Add(new DataColumn());
                          }

                          var row = ds.Tables["Table"].NewRow();
                          row[0] = "Test";

                          ds.Tables["Table"].Rows.Add(row);
                      });

    var excelReader = new ExcelReader(_mockConnection.Object, _mockAdapter.Object, _mockCommand.Object);
    excelReader.ReadCellsFromSpreadsheet("Deal Summary", cells);

    _mockCommand.VerifySet(c => c.CommandText = It.IsAny<string>(), Times.Exactly(cells.Count));
    _mockAdapter.VerifySet(a => a.SelectCommand = _mockCommand.Object, Times.Exactly(cells.Count));
    _mockAdapter.Verify(a => a.Fill(It.IsAny<DataSet>()), Times.Exactly(cells.Count));
}

这个实现有效,但是我觉得我做了太多的工作来模拟适配器...有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

一般来说,我有一些关于数据访问的规则:

  1. 编写一个包含所有数据访问逻辑的简单类,以便其他类不必处理DataAdapter和所有垃圾。
  2. 编写单元测试时,不要模拟DataAdapter;而只是模拟你刚刚创建的包装类。
  3. 使数据访问包装器逻辑变得如此简单,以至于它不需要进行单元测试。如果它需要进行测试,那么编写一个小型样本数据库的集成测试。

答案 1 :(得分:0)

不要将这3个对象作为参数传递。而是传递IDataReader,IDataProvider或类似于返回数据的那些。然后你只是模仿这个对象。并且您不需要在包含ExcellReader的项目中引用System.Data。

另外两件我不喜欢你的代码的事情。 为什么选择TestCase代替Test?

您确定要分别为每列创建命令和填充数据集吗? (但也许我不明白你的代码)