问题 模拟DataReader并获取Rhino.Mocks.Exceptions.ExpectationViolationException:IDisposable.Dispose();期望#0,实际#1


我正在尝试模拟一个SqlDataReader

 SqlDataReader reader = mocks.CreateMock<SqlDataReader>();
 Expect.Call(reader.Read()).Return(true).Repeat.Times(1);
 Expect.Call(reader.Read()).Return(false);
 Expect.Call(reader.HasRows).Return(true);
 Expect.Call(reader.Dispose);
 Expect.Call(reader["City"]).Return("Boise");
 Expect.Call(reader["State"]).Return("State");
 Expect.Call(reader["LAT"]).Return(100);
 Expect.Call(reader["LON"]).Return(-100);
 mocks.ReplayAll();

但我一直得到一个Rhino.Mocks.Exceptions.ExpectationViolationException:IDisposable.Dispose();在我的方法中预期#0,实际#1错误

        using (reader)
        {
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    CityState myCity = new CityState
                       {
                           City = reader["City"].ToString(),
                           State = reader["State"].ToString(),
                           Lat = Convert.ToInt32(reader["LAT"]),
                           Lon = Convert.ToInt32(reader["LON"])
                       };
                    myCities.Add(myCity);
                }                    
            }               
        }

我错过了什么吗?


6997
2017-11-24 21:18


起源



答案:


我建议你使用AAA语法和使用接口重写测试(IDataReader而不是具体类型(SqlDataReader):

// Arrange
IDataReader reader = MockRepository.GenerateStub<IDataReader>();
reader.Stub(x => x.Read()).Repeat.Once().Return(true);
reader.Stub(x => x.Read()).Return(false);
reader.Stub(x => x["City"]).Return("Boise");
reader.Stub(x => x["State"]).Return("State");
reader.Stub(x => x["LAT"]).Return(100);
reader.Stub(x => x["LON"]).Return(-100);

// Act
var myCities = new List<CityState>();
using (reader)
{
    while (reader.Read())
    {
        CityState myCity = new CityState
        {
            City = reader["City"].ToString(),
            State = reader["State"].ToString(),
            Lat = Convert.ToInt32(reader["LAT"]),
            Lon = Convert.ToInt32(reader["LON"])
        };
        myCities.Add(myCity);
    }
}

// Assert
Assert.AreEqual(1, myCities.Count);
Assert.AreEqual("Boise", myCities[0].City);
...

10
2017-11-24 21:47



我认为既然这个答案被接受了,它必定已经解决了问题。但问题仍然存在:它为什么有效?我对IDisposable有同样的问题(我正在尝试模拟System.IO.Stream),我无法弄清楚为什么我的存根Dispose()没有被调用。 - Bruce Johnston
它的工作原理是因为我 SqlDataReader 同 IDataReader 并嘲笑这个 IDataReader。在您的情况下,您似乎正在使用抽象类而不是接口。在这种情况下,您需要使用创建模拟对象 MockRepository.GeneratePartialMock<Stream>() 用它定义了对它的期望 streamMock.Expect(x => x.Dispose()).Throw(new Exception("foo"));。 - Darin Dimitrov
为CityState添加实现后,此示例是否在您的计算机上运行?如果没有,你能提供完整的代码,以便运行吗?即使在使用var reader = new Mock <IDataReader>()和reader.Setup(...)之后,它也不适用于Moq 4.0.10827。 - Lernkurve


答案:


我建议你使用AAA语法和使用接口重写测试(IDataReader而不是具体类型(SqlDataReader):

// Arrange
IDataReader reader = MockRepository.GenerateStub<IDataReader>();
reader.Stub(x => x.Read()).Repeat.Once().Return(true);
reader.Stub(x => x.Read()).Return(false);
reader.Stub(x => x["City"]).Return("Boise");
reader.Stub(x => x["State"]).Return("State");
reader.Stub(x => x["LAT"]).Return(100);
reader.Stub(x => x["LON"]).Return(-100);

// Act
var myCities = new List<CityState>();
using (reader)
{
    while (reader.Read())
    {
        CityState myCity = new CityState
        {
            City = reader["City"].ToString(),
            State = reader["State"].ToString(),
            Lat = Convert.ToInt32(reader["LAT"]),
            Lon = Convert.ToInt32(reader["LON"])
        };
        myCities.Add(myCity);
    }
}

// Assert
Assert.AreEqual(1, myCities.Count);
Assert.AreEqual("Boise", myCities[0].City);
...

10
2017-11-24 21:47



我认为既然这个答案被接受了,它必定已经解决了问题。但问题仍然存在:它为什么有效?我对IDisposable有同样的问题(我正在尝试模拟System.IO.Stream),我无法弄清楚为什么我的存根Dispose()没有被调用。 - Bruce Johnston
它的工作原理是因为我 SqlDataReader 同 IDataReader 并嘲笑这个 IDataReader。在您的情况下,您似乎正在使用抽象类而不是接口。在这种情况下,您需要使用创建模拟对象 MockRepository.GeneratePartialMock<Stream>() 用它定义了对它的期望 streamMock.Expect(x => x.Dispose()).Throw(new Exception("foo"));。 - Darin Dimitrov
为CityState添加实现后,此示例是否在您的计算机上运行?如果没有,你能提供完整的代码,以便运行吗?即使在使用var reader = new Mock <IDataReader>()和reader.Setup(...)之后,它也不适用于Moq 4.0.10827。 - Lernkurve