无法让 RhinoMock 迭代 DataReader
我正在尝试使用 RhinoMocks 模拟 IDataReader,但我很难让它迭代 DataRows。这是我到目前为止所做的:
[TestFixture]
public sealed class TestStubbedDataReader
{
private int currentRowIdx; //The current position in the datareader
private bool notAtEnd; //Return value of the Reader.Read method
private int countOfRows; //Count of rows in the dataReader
private IList<IDataRecord> rows; //The datarecords that the reader should iterate through
[Test]
public void TestDataReader()
{
//Mock the reader
MockRepository mockRepository = new MockRepository();
IDataReader reader = mockRepository.Stub<IDataReader>();
//Build a list of IDataRecords to for the datareader with two records.
//It mocks a simple table with a Int32 Id field and a string Name field.
rows = new List<IDataRecord>()
{
new RowBuilder().WithValues(1, "AAA").Build(),
new RowBuilder().WithValues(1, "BBB").Build()
};
//Initializing variables for iteration
currentRowIdx = 0;
notAtEnd = true;
countOfRows = rows.Count;
//NOTE: It is probably here I am doing something wrong!!
//Seting up results for for reading the fields of the current record.
SetupResult.For(reader.GetInt32(0)).Return(rows[currentRowIdx].GetInt32(0));
SetupResult.For(reader.GetString(1)).Return(rows[currentRowIdx].GetString(1));
//Seting up returnValue for Reader.Read().
//Call back increases the currentRowIdx or sets notAtEnd flag to False
SetupResult.For(reader.Read()).Return(notAtEnd).Callback(new CallBackDelegate(MoveToNextRecord));
mockRepository.ReplayAll();
Int32 previousId = -1;
string previousName = string.Empty;
//Here I iterate through the DataReader.
while (reader.Read())
{
Console.WriteLine("Read ID: " + reader.GetInt32(0) + " Name: " + reader.GetString(1));
//dataValueObjects.Add(new ToxDataValueObject(reader));
Console.WriteLine("Read");
Assert.That(reader.GetInt32(0), !Is.EqualTo(previousId), "Id is the same as in the previous record");
Assert.That(reader.GetString(1), !Is.EqualTo(previousName), "Name is the same as in the previous record");
previousId = reader.GetInt32(0);
previousName= reader.GetString(1);
}
}
public delegate bool CallBackDelegate();
private bool MoveToNextRecord()
{
if (currentRowIdx<= countOfRows) //Not at the end yet; increas
{
currentRowIdx++;
}
else //At the end. Next time, Reader.Read should return False
{
notAtEnd = false;
}
return notAtEnd;
}
}
//Builder for DataRows
internal class RowBuilder
{
private MockRepository _mockRepository;
private IDataRecord _dataRecord;
public RowBuilder()
{
//Initialise and create stubbed datarecord.
_mockRepository = new MockRepository();
_dataRecord = _mockRepository.Stub<IDataRecord>();
}
//Set return values, and return builder
public RowBuilder WithValues(int id, string name)
{
SetupResult.For(_dataRecord.GetInt32(0)).Return(id);
SetupResult.For(_dataRecord.GetString(1)).Return(name);
return this;
}
//Return the mocked DataRow
public IDataRecord Build()
{
_mockRepository.ReplayAll();
return _dataRecord;
}
}
读取器按预期循环两次,但第二次迭代的返回值与第一次相同。应该怎么办???
I am trying to mock IDataReader with RhinoMocks, but I am having a hard time making it iterate through the DataRows. Here is what I have done so far:
[TestFixture]
public sealed class TestStubbedDataReader
{
private int currentRowIdx; //The current position in the datareader
private bool notAtEnd; //Return value of the Reader.Read method
private int countOfRows; //Count of rows in the dataReader
private IList<IDataRecord> rows; //The datarecords that the reader should iterate through
[Test]
public void TestDataReader()
{
//Mock the reader
MockRepository mockRepository = new MockRepository();
IDataReader reader = mockRepository.Stub<IDataReader>();
//Build a list of IDataRecords to for the datareader with two records.
//It mocks a simple table with a Int32 Id field and a string Name field.
rows = new List<IDataRecord>()
{
new RowBuilder().WithValues(1, "AAA").Build(),
new RowBuilder().WithValues(1, "BBB").Build()
};
//Initializing variables for iteration
currentRowIdx = 0;
notAtEnd = true;
countOfRows = rows.Count;
//NOTE: It is probably here I am doing something wrong!!
//Seting up results for for reading the fields of the current record.
SetupResult.For(reader.GetInt32(0)).Return(rows[currentRowIdx].GetInt32(0));
SetupResult.For(reader.GetString(1)).Return(rows[currentRowIdx].GetString(1));
//Seting up returnValue for Reader.Read().
//Call back increases the currentRowIdx or sets notAtEnd flag to False
SetupResult.For(reader.Read()).Return(notAtEnd).Callback(new CallBackDelegate(MoveToNextRecord));
mockRepository.ReplayAll();
Int32 previousId = -1;
string previousName = string.Empty;
//Here I iterate through the DataReader.
while (reader.Read())
{
Console.WriteLine("Read ID: " + reader.GetInt32(0) + " Name: " + reader.GetString(1));
//dataValueObjects.Add(new ToxDataValueObject(reader));
Console.WriteLine("Read");
Assert.That(reader.GetInt32(0), !Is.EqualTo(previousId), "Id is the same as in the previous record");
Assert.That(reader.GetString(1), !Is.EqualTo(previousName), "Name is the same as in the previous record");
previousId = reader.GetInt32(0);
previousName= reader.GetString(1);
}
}
public delegate bool CallBackDelegate();
private bool MoveToNextRecord()
{
if (currentRowIdx<= countOfRows) //Not at the end yet; increas
{
currentRowIdx++;
}
else //At the end. Next time, Reader.Read should return False
{
notAtEnd = false;
}
return notAtEnd;
}
}
//Builder for DataRows
internal class RowBuilder
{
private MockRepository _mockRepository;
private IDataRecord _dataRecord;
public RowBuilder()
{
//Initialise and create stubbed datarecord.
_mockRepository = new MockRepository();
_dataRecord = _mockRepository.Stub<IDataRecord>();
}
//Set return values, and return builder
public RowBuilder WithValues(int id, string name)
{
SetupResult.For(_dataRecord.GetInt32(0)).Return(id);
SetupResult.For(_dataRecord.GetString(1)).Return(name);
return this;
}
//Return the mocked DataRow
public IDataRecord Build()
{
_mockRepository.ReplayAll();
return _dataRecord;
}
}
The reader loops twice as intended, but the return values of the second iteration are identical to the first. What should be done???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的建议:避免模拟具有潜在复杂(和隐藏)行为的组件。相反,以不太通用的方式定义一个适合您需求的适配器接口,并在代码中使用它而不是
IDataReader
。然后模拟该接口,这应该是一个简单得多的任务。在生产代码中,定义并使用与真实的 IDataReader 一起使用的适配器接口的实现。
My suggestion: avoid mocking components with potentially complex (and hidden) behavior. Instead, define an adapter interface that suits your needs in a less generic way and use it in your code instead of the
IDataReader
. Then mock that interface, which should be a much simpler task.In the production code, define and use an implementation of your adapter interface which works with real
IDataReader
s.