使用 Moq 模拟 IDbDataAdapter 填充方法

发布于 2024-11-29 21:33:26 字数 1749 浏览 1 评论 0原文

我有一个使用 IDbConnectionIDbDataAdapterIDbCommand 从 Excel 文件读取数据的对象。我使用适配器填充方法用数据填充表,这就是我当前模拟它的方式:

[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));
}

此实现有效,但我觉得我在模拟适配器方面做得太多了...有没有更好的方法做这个吗?

I have an object that reads data from an Excel file using, which takes a IDbConnection, IDbDataAdapter and an IDbCommand. I use the adapters fill method to populate a table with data, and this is how I am currently mocking it:

[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));
}

This implementation works, but I feel like I'm doing too much to Mock the adapter... is there a better way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初心未许 2024-12-06 21:33:26

不要将这 3 个对象作为参数传递。相反,传递 IDataReader、IDataProvider 或类似返回数据的东西。然后你只需模拟这个对象。并且您不需要在包含 ExcellReader 的项目中引用 System.Data。

还有两件事我不喜欢你的代码。
为什么使用测试用例而不是测试?

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

Do not pass those 3 objects as parameters. Instead pass IDataReader, IDataProvider or sth like that that returns data. Then You just mock this object. And you don't need reference to System.Data in project containing ExcellReader.

And two other things I don't like about your code.
Why TestCase instead of Test?

Are you sure you want to create command and fill dataset for each column separately? (but maybe I don't understand your code)

淡淡の花香 2024-12-06 21:33:26

一般来说,我对数据访问有一些规则:

  1. 编写一个简单的类来包装所有数据访问逻辑,以便其他类不必处理 DataAdapter 和所有那些废话。
  2. 当你编写单元测试时,不要模拟 DataAdapter;相反,只需模拟您刚刚创建的包装类。
  3. 使数据访问包装器逻辑如此简单,以至于实际上不需要进行单元测试。如果确实需要测试,则编写针对小型示例数据库的集成测试。

In general, I have some rules about data access:

  1. Write a simple class that wraps all the data access logic, so that other classes don't have to deal with DataAdapters and all that crap.
  2. When you write unit tests, don't mock out DataAdapters; instead just mock out the wrapper classes that you just created.
  3. Make the data access wrapper logic so simple that it doesn't really need to be unit tested. If it DOES need to be tested, then write integration tests that hit a small sample database.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文