使用Rhino Mocks“类型的奇怪错误与返回值不匹配”

时间:2013-07-15 18:03:42

标签: c# rhino-mocks

编辑:我玩过这个例子,现在是my question is a different one entirely

当我运行这个例子时:

using Rhino.Mocks;

public interface IInterface
{
    decimal GetDecimal();
}

static class Util
{
    public static double? DecToDouble(this IInterface input)
    {
        return (double) input.GetDecimal();
    }
}

class MockExample
{
    public void RunThis()
    {
        var stubReader = MockRepository.GenerateStub<IInterface>();
        stubReader.Stub(sr => sr.DecToDouble()).Return(1.2);
    }
}

我收到此错误:

  

System.InvalidOperationException:类型'System.Double'与方法'IInterface.GetDecimal();'

的返回类型'System.Decimal'不匹配

为什么?

2 个答案:

答案 0 :(得分:4)

Rhino Mocks只能拦截通过存根接口进行的调用。上面的扩展方法编译为:

Util.DecToDouble(sr)

这意味着您的设置/返回基本上如下所示:

stubReader.Stub(sr => Util.DecToDouble(sr)).Return(1.2);

这显然不会起作用(大多数模拟框架)。实现目标的正确方法是:

stubReader.Stub(sr => sr.GetDecimal())).Return(1.2);

经过进一步调查后 Rhino Mocks通过调用传递给Stub()的委托并保存最后一次应用的方法调用,将Stub()声明的方法内部连接到Return()声明的值。此保存的方法调用随后连接到返回值。执行此操作时,Rhino Mocks会在内部检查已保存调用的返回类型是否与值的类型匹配。如果他们不匹配Rhino Mocks会引发您所看到的异常。定义存根的正确方法是

    decimal val = 1.2M;
    stubReader.Stub(sr => sr.DecToDouble()).Return(val);

但是这不能编译,因为Stub()和Return()的泛型类型参数必须兼容。所以真正定义存根的唯一方法是忽略扩展方法,只存根接口中定义的方法。

答案 1 :(得分:0)

如果你试图模仿IInterface,那么你就是错误的方法:

public void RunThis()
{
    var stubReader = MockRepository.GenerateStub<IInterface>();
    stubReader.Stub(sr => sr.GetDecimal()).Return(1.2);
}

如果您尝试存根DecToDouble,则无法使用RhinoMocks。扩展方法被编译为静态方法调用,RhinoMocks无法对其进行模拟,因为它们在编译时被绑定。一些存根框架使用低级探查器调用来拦截静态调用,但RhinoMocks没有我所知道的那种功能。

有关类似的讨论,请参阅this question