我是否可以创建一个SqlDataReader并为其提供值,而无需从另一个对象返回SqlDataReader,例如SqlCommand.ExecuteReader()

时间:2012-12-20 15:53:52

标签: c# .net unit-testing mocking moq

我正在为我的数据访问层编写单元测试。为了实现这一点,我已经为SqlCommand(ISqlCommand)创建了一个包装器,以便我可以模拟它的功能。

ISqlCommand command = _connection.GetSqlCommand(sqlCommand);

在我测试的其中一个方法中,正在调用SqlCommand的ExecuteReader方法,我必须返回一个SqlDataReader。

SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleRow);

在同一方法中,reader.Read将被调用

if (reader.Read())
{
    someVariable = reader.GetString(1);
}

我想要的是能够从模拟的command.ExecuteReader()返回一个SqlDataReader对象,其值为Read to Read。可以吗?似乎SqlDataReader只能从正在运行的实际SqlCommand.ExecuteReader实例化并返回SqlDataReader。 完整的相关代码待测。

ISqlCommand command = _connection.GetSqlCommand(sqlCommand);

using (command)
{
    SqlDataReader reader =  command.ExecuteReader(CommandBehavior.SingleRow);

    if (reader.Read())
    {
        dbVersion = reader.GetString(1);
    }
}

编辑:清楚我要问的是什么。 SqlDatareader没有公共构造函数。据我所知,我无法使用该类编写任何测试,因为我无法在不使用SqlCommand对数据库进行合法调用的情况下对其进行实例化。即使尝试创建SqlDataReaderWrapper的接口也无济于事,因为问题是相同的。我不是在尝试编写集成测试(对数据库进行实际调用),因此DataReader似乎无法按原样进行测试。我的问题是,在这种情况下,我可以做什么,将值放入SqlDataReader?

1 个答案:

答案 0 :(得分:3)

我假设你没有使用模拟框架。这样做会有所帮助,但您应该按照上面的建议模拟IDataReader。以下是使用RhinoMocks的上一个问题。这可能有所帮助。

Mocking a DataReader and getting a Rhino.Mocks.Exceptions.ExpectationViolationException: IDisposable.Dispose(); Expected #0, Actual #1

另外,我注意到你做了一个ISqlCommand,我建议你使用IDbCommand,它是开箱即用的界面,会让你的测试变得不那么脆弱,因为如果需要的话它会允许替换其他命令对象。

我只是嘲笑数据阅读器,运行良好:

 Mock<IDataReader> mockDataReader = new Mock<IDataReader>();
 bool success = true;
 mockDataReader.Setup(x => x.Read())
               .Returns(() => success).Callback(() => success = false);
 Assert.IsTrue(mockDataReader.Object.Read());

以下是一个很好的例子:http://www.codeproject.com/Articles/478504/Moq-Mock-Database