如何模拟IDataReader以测试将SqlDataReader转换为System.DataView的方法 [英] How to mock IDataReader to test method which converts SqlDataReader to System.DataView

查看:162
本文介绍了如何模拟IDataReader以测试将SqlDataReader转换为System.DataView的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Moq的新手,我正努力编写单元测试来测试将SqlDataAdapter转换为System.DataView的方法.这是我的方法:

I'm new to Moq and I'm struggling to write Unit Test to test a method which converts SqlDataAdapter to System.DataView. This is my method:

private DataView ResolveDataReader(IDataReader dataReader)
{
    DataTable table = new DataTable();

    for (int count = 0; count < dataReader.FieldCount; count++)
    {
        DataColumn col = new DataColumn(dataReader.GetName(count), 
                                        dataReader.GetFieldType(count));
        table.Columns.Add(col);
    }

    while (dataReader.Read())
    {
        DataRow dr = table.NewRow();
        for (int i = 0; i < dataReader.FieldCount; i++)
        {
            dr[i] = dataReader.GetValue(dataReader.GetOrdinal(dataReader.GetName(i)));
        }
        table.Rows.Add(dr);
    }

    return table.DefaultView;
}

我正在尝试创建类似以下内容的

I'm trying to create to create something like:

var dataReaderMock = new Mock<IDataReader>();
var records = new Mock<IDataRecord>();
dataReaderMock.Setup(x => x.FieldCount).Returns(2);
dataReaderMock.Setup(x => x.Read()).Returns(() => records);

我想传递一些数据并验证其是否已转换.

I would like to pass some data and verify that it is converted.

谢谢.

推荐答案

您在使用模拟程序时走在正确的轨道上,但是dataReaderMock.Setup(x => x.Read()).Returns(() => records);是您出错的地方,因为.Read返回布尔值,而不是记录本身,这被您的方法读出IDataReader.

You were on the right track with your mocks, but dataReaderMock.Setup(x => x.Read()).Returns(() => records); is where you went wrong as .Read returns a bool, not the records themselves, which are read out the IDataReader by your method.

安排模拟:

var dataReader = new Mock<IDataReader>();
dataReader.Setup(m => m.FieldCount).Returns(2); // the number of columns in the faked data

dataReader.Setup(m => m.GetName(0)).Returns("First"); // the first column name
dataReader.Setup(m => m.GetName(1)).Returns("Second"); // the second column name

dataReader.Setup(m => m.GetFieldType(0)).Returns(typeof(string)); // the data type of the first column
dataReader.Setup(m => m.GetFieldType(1)).Returns(typeof(string)); // the data type of the second column

您可以安排各列的口味,以模拟系统中的更多真实数据,类型等.只需确保第一个计数,GetName的数量和 s是同步的.

You can arrange the columns to taste to simulate more real data, types etc.. in your system, just ensure the first count, the number of GetNames and the number of GetFieldTypes are in sync.

要安排.Read(),我们可以使用SetupSequence:

To arrange the .Read(), we can use SetupSequence:

dataReader.SetupSequence(m => m.Read())
    .Returns(true) // Read the first row
    .Returns(true) // Read the second row
    .Returns(false); // Done reading

要在测试中使用它,您可以将其提取为一种方法:

To use this in tests you can extract it into a method:

private const string Column1 = "First";
private const string Column2 = "Second";
private const string ExpectedValue1 = "Value1";
private const string ExpectedValue2 = "Value1";

private static Mock<IDataReader> CreateDataReader()
{
    var dataReader = new Mock<IDataReader>();

    dataReader.Setup(m => m.FieldCount).Returns(2);
    dataReader.Setup(m => m.GetName(0)).Returns(Column1);
    dataReader.Setup(m => m.GetName(1)).Returns(Column2);

    dataReader.Setup(m => m.GetFieldType(0)).Returns(typeof(string));
    dataReader.Setup(m => m.GetFieldType(1)).Returns(typeof(string));

    dataReader.Setup(m => m.GetOrdinal("First")).Returns(0);
    dataReader.Setup(m => m.GetValue(0)).Returns(ExpectedValue1);
    dataReader.Setup(m => m.GetValue(1)).Returns(ExpectedValue2);

    dataReader.SetupSequence(m => m.Read())
        .Returns(true)
        .Returns(true)
        .Returns(false);
    return dataReader;
}

(或者,您也可以将其安排在Setup上,如果这对您的测试类更有意义-在这种情况下,dataReader模拟将是一个字段,而不是返回值)

(Alternatively, you could arrange this on a Setup, if that makes more sense for your test class - in that case the dataReader mock would be a field, not a returned value)

示例测试.然后可以像这样使用它:

Example Tests. Then it can be used like:

[Test]
public void ResovleDataReader_RowCount()
{
    var dataReader = CreateDateReader();
    var view = ResolveDataReader(dataReader.Object);
    Assert.AreEqual(2, view.Count);
}

[Test]
public void ResolveDataReader_NamesColumn1()
{
    var dataReader = CreateDataReader();
    var view = ResolveDataReader(dataReader.Object);
    Assert.AreEqual(Column1, view.Table.Columns[0].ColumnName);
}

[Test]
public void ResolveDataReader_PopulatesColumn1()
{
    var dataReader = CreateDataReader();
    var view = ResolveDataReader(dataReader.Object);
    Assert.AreEqual(ExpectedValue1, view.Table.Rows[0][0]);
}

// Etc..

(我使用过NUnit,但是在不同的测试框架中,测试方法只有一个不同的属性,而assert语法也有所不同)

顺便说一句,我通过将ResolveDataReader更改为internal并设置了InternalsVisibleTo来完成上述工作,但我认为您已经可以使用此私有方法了尝试测试.

As an aside, I got the above to work by changing ResolveDataReader to internal and setting InternalsVisibleTo, but I assume you have a gateway into this private method as you've got as far as you did with trying to test it.

这篇关于如何模拟IDataReader以测试将SqlDataReader转换为System.DataView的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆