如何模拟IDataReader以测试将SqlDataReader转换为System.DataView的方法 [英] How to mock IDataReader to test method which converts SqlDataReader to 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
的数量和
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 GetName
s and the number of GetFieldType
s 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屋!