为什么鼹鼠不返回“moled”?模拟 SqlDataAdaptor 时的 DataSet?

发布于 2024-11-08 08:01:08 字数 3036 浏览 0 评论 0原文

我刚刚开始使用 Moles 来模拟一些棘手的遗留代码。本质上,我正在尝试让 SqlDataAdapter 与 Moles 一起使用。 (顺便说一句,我已经成功地将moles与SqlDataReader和SqlCommand类一起使用。)我尝试在下面创建一个“简单”单元测试示例,我试图让SqlDataAdaptor“填充”提供的数据集。然后,当使用 Moles 时,我会模拟从数据集中检索数据的各种调用。我相信我已经正确设置了数据集,以便数据检索将返回预期的“模制”对象并做正确的事情。

当我运行下面的代码时,我可以看到 FillDataSetString lambda 表达式正在执行,并且“d”被设置为“moled”ds。但是当 Fill 方法返回时,传入的 DataSet(“dset”)仍然是常规的“DataSet”,而不是“模制的 DataSet”。因此,第一个 Assert 无法正确运行并抛出 IndexOutOfRangeException(“找不到表 0”)。在第一个断言中,我期望在评估 dset.Tables[0].Rows.Count 时调用以下“模制”方法:

    ds.TablesGet
    tables.ItemGetInt32
    table.RowsGet
    rows.CountGet

但由于 dset 不是“模制”数据集,因此这些调用都不会发生。任何帮助弄清楚 Moles 使用 SqlDataAdapter 的数据集参数做什么的帮助将不胜感激。

要使以下功能正常工作,您必须安装“Moles”,引用 System.Data、System.Xml,创建“System.Data.moles”引用。我使用 Moles 框架 0.94.0.0 并在 VS.NET 2010 中运行它,测试项目的“目标框架”设置为“.NET Framework 4.0”。

using System.Data;
using System.Data.Moles;
using System.Data.Common.Moles;
using System.Data.SqlClient;
using System.Data.SqlClient.Moles;
using System.Xml.Serialization;

[TestClass]
public class UnitTest1
{

    [TestMethod]
    [HostType("Moles")]
    public void IsolatedSqlDataAdaptorTest()
    {
        // Arrange
        Dictionary<string, object> backing = new Dictionary<string, object>() 
        {
            {"field", 5},
        };

        MSqlConnection.AllInstances.Open = (c) => { };
        MSqlConnection.AllInstances.Close = (c) => { };
        MSqlDataAdapter.ConstructorStringSqlConnection =
        (@this, cmd, conn) =>
        {
            // Setup a moled DataSet with 1 Table and 1 Row
            MDataRow row = new MDataRow()
            {
                // This is the method that ultimately gets called.
                ItemGetString = (key) => { return backing[key]; },
            };

            MDataRowCollection rows = new MDataRowCollection();
            rows.CountGet = () => { return 1; };
            rows.ItemGetInt32 = (i) => { return row; };

            MDataTable table = new MDataTable();
            table.RowsGet = () => { return rows; };

            MDataTableCollection tables = new MDataTableCollection();
            tables.ItemGetInt32 = (i) => { return table; };

            MDataSet ds = new MDataSet();
            ds.TablesGet = () => { return tables; };

            MSqlDataAdapter sdaMole = new MSqlDataAdapter(@this);
            MDbDataAdapter ddaMole = new MDbDataAdapter(sdaMole)
            {
                FillDataSetString = (d, s) =>
                {
                    d = ds;
                    return 1;
                },
            };
        };

        // Act
        DataSet dset = new DataSet();
        SqlDataAdapter da = new SqlDataAdapter(
            "select something from aTable",
            new SqlConnection());
        da.Fill(dset, "aTable");

        // Assert
        Assert.AreEqual(1, dset.Tables[0].Rows.Count, "Count");
        Assert.AreEqual(5, dset.Tables[0].Rows[0]["field"], "field");
    }
}

I've just started to use Moles to mock some tricky legacy code. In essence, I'm trying get a SqlDataAdapter to work with Moles. (BTW, I've been successful using moles with the SqlDataReader and SqlCommand classes.) I've tried to create a "simple" unit test example below where I'm trying to get SqlDataAdaptor to "fill" the provided DataSet. Then when using Moles, I'm mocking the various calls in retrieving data from the data set. I believe I have set the DataSet up correctly so that retrieval of data will return the expected "moled" object and do the right thing.

When I run the below I can see that FillDataSetString lambda expression is being executed and "d" is being set to the "moled" ds. But when the Fill method returns, the DataSet passed in ("dset") is still a regular "DataSet" and not the "moled DataSet". Thus the first Assert doesn't operate correctly and throws an IndexOutOfRangeException ("Cannot find table 0."). In the first Assert, I'm expecting the following "moled" methods to be called when dset.Tables[0].Rows.Count is evaluated:

    ds.TablesGet
    tables.ItemGetInt32
    table.RowsGet
    rows.CountGet

But since dset is not not the "moled" DataSet, none of those calls happen. Any help figuring out what Moles is doing with SqlDataAdapter's dataset parameter would be much appreciated.

To get the below to work, you must install "Moles", reference System.Data, System.Xml, create a "System.Data.moles" reference. I'm using 0.94.0.0 of the Moles framework and running this in VS.NET 2010, with the test project's "Target Framework" set as ".NET Framework 4.0".

using System.Data;
using System.Data.Moles;
using System.Data.Common.Moles;
using System.Data.SqlClient;
using System.Data.SqlClient.Moles;
using System.Xml.Serialization;

[TestClass]
public class UnitTest1
{

    [TestMethod]
    [HostType("Moles")]
    public void IsolatedSqlDataAdaptorTest()
    {
        // Arrange
        Dictionary<string, object> backing = new Dictionary<string, object>() 
        {
            {"field", 5},
        };

        MSqlConnection.AllInstances.Open = (c) => { };
        MSqlConnection.AllInstances.Close = (c) => { };
        MSqlDataAdapter.ConstructorStringSqlConnection =
        (@this, cmd, conn) =>
        {
            // Setup a moled DataSet with 1 Table and 1 Row
            MDataRow row = new MDataRow()
            {
                // This is the method that ultimately gets called.
                ItemGetString = (key) => { return backing[key]; },
            };

            MDataRowCollection rows = new MDataRowCollection();
            rows.CountGet = () => { return 1; };
            rows.ItemGetInt32 = (i) => { return row; };

            MDataTable table = new MDataTable();
            table.RowsGet = () => { return rows; };

            MDataTableCollection tables = new MDataTableCollection();
            tables.ItemGetInt32 = (i) => { return table; };

            MDataSet ds = new MDataSet();
            ds.TablesGet = () => { return tables; };

            MSqlDataAdapter sdaMole = new MSqlDataAdapter(@this);
            MDbDataAdapter ddaMole = new MDbDataAdapter(sdaMole)
            {
                FillDataSetString = (d, s) =>
                {
                    d = ds;
                    return 1;
                },
            };
        };

        // Act
        DataSet dset = new DataSet();
        SqlDataAdapter da = new SqlDataAdapter(
            "select something from aTable",
            new SqlConnection());
        da.Fill(dset, "aTable");

        // Assert
        Assert.AreEqual(1, dset.Tables[0].Rows.Count, "Count");
        Assert.AreEqual(5, dset.Tables[0].Rows[0]["field"], "field");
    }
}

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

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

发布评论

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

评论(1

猫弦 2024-11-15 08:01:08

在 @StingyJack 的建议提示下,几个月后重新审视这个问题,模拟 Fill 方法,我想出了以下内容来支持我的模拟要求。它仍然没有真正回答为什么数据集没有被我的模型数据集替换。

    [TestMethod]
    [HostType("Moles")]
    public void IsolatedSqlDataAdaptorTestWithFill()
    {
        // Arrange
        MSqlConnection.AllInstances.Open = c => { };
        MSqlConnection.AllInstances.Close = c => { };
        MSqlDataAdapter.ConstructorStringSqlConnection = (@this, cmd, conn) => { };
        MDbDataAdapter.AllInstances.FillDataSetString = (da, ds, s) =>
            {
                var dt = new DataTable(s);
                dt.Columns.Add(new DataColumn("string", typeof(string)));
                dt.Columns.Add(new DataColumn("int", typeof(int)));
                dt.Rows.Add("field", 5);
                ds.Tables.Add(dt);
                return 1;
            };

        // Act
        using (var dset = new DataSet())
        {
            using (var conn = new SqlConnection())
            {
                using (var da = new SqlDataAdapter("select something from aTable", conn))
                {
                    da.Fill(dset, "aTable");
                }
            }

            // Assert
            Assert.AreEqual(1, dset.Tables[0].Rows.Count, "Count");
            Assert.AreEqual("field", dset.Tables[0].Rows[0]["string"], "string");
            Assert.AreEqual(5, dset.Tables[0].Rows[0]["int"], "int");
        }
    }

Taking a fresh look at this question after a number of months as prompted by a suggestion, by @StingyJack, to mock the Fill method, I came up with the following to support my mocking requirements. It still doesn't really answer why the dataset was not being replaced with my moled dataset.

    [TestMethod]
    [HostType("Moles")]
    public void IsolatedSqlDataAdaptorTestWithFill()
    {
        // Arrange
        MSqlConnection.AllInstances.Open = c => { };
        MSqlConnection.AllInstances.Close = c => { };
        MSqlDataAdapter.ConstructorStringSqlConnection = (@this, cmd, conn) => { };
        MDbDataAdapter.AllInstances.FillDataSetString = (da, ds, s) =>
            {
                var dt = new DataTable(s);
                dt.Columns.Add(new DataColumn("string", typeof(string)));
                dt.Columns.Add(new DataColumn("int", typeof(int)));
                dt.Rows.Add("field", 5);
                ds.Tables.Add(dt);
                return 1;
            };

        // Act
        using (var dset = new DataSet())
        {
            using (var conn = new SqlConnection())
            {
                using (var da = new SqlDataAdapter("select something from aTable", conn))
                {
                    da.Fill(dset, "aTable");
                }
            }

            // Assert
            Assert.AreEqual(1, dset.Tables[0].Rows.Count, "Count");
            Assert.AreEqual("field", dset.Tables[0].Rows[0]["string"], "string");
            Assert.AreEqual(5, dset.Tables[0].Rows[0]["int"], "int");
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文