编辑:我玩过这个例子,现在是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'不匹配
为什么?
答案 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。