5

我正在为我的数据访问层编写单元测试。为了实现这一点,我为 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 对象,并提供一个值供我阅读。可以做到吗?似乎 SqlDataReader 只能从正在运行并返回 SqlDataReader 的实际 SqlCommand.ExecuteReader 实例化。要测试的完整相关代码。

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 中吗?

4

1 回答 1

3

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

模拟 DataReader 并获得 Rhino.Mocks.Exceptions.ExpectationViolationException: IDisposable.Dispose(); 预期 #0,实际 #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

于 2012-12-20T17:19:30.507 回答