模拟datareader在第二次调用时失败

时间:2011-09-03 19:29:27

标签: unit-testing nhibernate mocking rhino-mocks

在下面的测试中,模拟的datareader第一次返回所需的值,但是当索引应为1时返回相同的值。

我是否滥用dataReader或Rhino存根语法?有什么问题?

干杯,
Berryl

测试失败

[Test]
public void NullSafeGet_GetsBothProperties()
{
    var sessionImplementor = MockRepository.GenerateStub<ISessionImplementor>();
    var userType = new DateRangeUserType();

    var reader = MockRepository.GenerateStub<IDataReader>();           
    var start = new DateTime(2011, 6, 1);
    var end = new DateTime(2011, 7, 1);
    reader.Stub(x => x[0]).Return(start);
    reader.Stub(x => x[1]).Return(end);    ***<==== returns Jun 1 instead of Jul1

    var result = userType.NullSafeGet(reader, userType.PropertyNames, sessionImplementor, null);
    Assert.That(result, Is.EqualTo(new DateRange(start, end, DateRange.MaxSupportedPrecision)));

}
Expected: <6/1/2011 12:00 AM - 7/1/2011 12:00 AM>
But was:  <6/1/2011 12:00 AM - 6/1/2011 12:00 AM>

SUT(NHib CompositeUserType方法)

public override object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner) {
    if (dr == null) return null;

    var foundStart = (DateTime)NHibernateUtil.DateTime.NullSafeGet(dr, names[0], session, owner);
    var foundEnd = (DateTime)NHibernateUtil.DateTime.NullSafeGet(dr, names[1], session, owner);

    var precision = DateRange.MaxSupportedPrecision;
    var startDp = _getDatePoint(foundStart, precision);
    var endDp = _getDatePoint(foundEnd, precision);

    return new DateRange(startDp, endDp, precision);
}

1 个答案:

答案 0 :(得分:1)

你并没有嘲笑NHibernate调用的所有内容。这大致是NHibernate与读者的关系:

...
int index = reader.GetOrdinal(name);
...
if (reader.IsDBNull(index)) {
    return null;
} else {
    ...
    val = rs[index];
    ...
}

Rhino生成的存根将返回0以响应两个GetOrdinal调用,这就是为什么它将两次都返回June1。您可以尝试通过模拟GetOrdinal和索引器来修复它。像这样:

var reader = MockRepository.GenerateStub<IDataReader>();
var start = new DateTime(2011, 6, 1);
var end = new DateTime(2011, 7, 1);

reader.Stub(x => x.GetOrdinal(userType.PropertyNames[0])).Return(0);
reader.Stub(x => x.GetOrdinal(userType.PropertyNames[1])).Return(1);

reader.Stub(x => x[0]).Return(start);
reader.Stub(x => x[1]).Return(end);

但是,您是否真的需要重新考虑是否确实需要单元测试UserType。除了调用NHibernate之外,它没有很多责任。单元测试此类需要您模拟您不拥有的类型(MS IDataReader)。更糟糕的是,这个模拟被另一个第三方(NHibernate)使用。基本上你需要查看NHibernate源代码(这就是我所做的)来创建一个正确的存根。看看this article。它详细介绍了为什么你应该避免嘲笑你不拥有的类型。您可能最好使用in-memory sqlite database为此课程编写集成测试。