打桩静态扩展方法似乎犀牛制品工作,除非我投返回变量。为什么? [英] Stubbing a static extension method seems to work in Rhino Mocks unless I cast the return variable. Why?
问题描述
我能够使用存根犀牛制品的静态扩展方法,但如果我将返回值转换为另一种类型,我得到一个错误。为什么?
使用Rhino.Mocks;
公共接口INumberGenerator
{
双GetDouble();
}
静态类NumberGeneratorExtensionMethods
{
公共静态双GetTheDouble(此INumberGenerator输入)
{
返回input.GetDouble();
}
公共静态十进制GetTheDoubleCastToDecimal(此INumberGenerator输入)
{
回报(十进制)input.GetDouble();
}
}
类MockExample
{
公共无效TriggerTheError()
{
VAR存根= MockRepository.GenerateStub< INumberGenerator>();
//此工程
stub.Stub(OBJ => obj.GetTheDouble())返回(1.2D)。
//这引发错误
stub.Stub(OBJ => obj.GetTheDoubleCastToDecimal())返回(1.2米)。
}
}
下面是错误:
System.InvalidOperationException:类型System.Decimal不适用于匹配方法的返回类型'System.Double'INumberGenerator.GetDouble();
块引用>
解决方案警告:这是一个真正的怀疑比什么都重要
的问题是,你没有的真正的存根扩展方法在所有 - 你删
GetDouble
在这两种情况下。
我没有看过的犀牛制品的代码一段时间,但我的犯罪嫌疑人的那在
存根
方法基本上是说:
- 准备好上模拟一些调用!
- 调用传递作为参数
- 的委托注意它要求作了
这意味着你有效地这样做:
canGetDecimal.Stub(纳克=> ng.GetDouble())返回(1.2D)。
canGetDecimal.Stub(NG =>(十进制)ng.GetDouble())返回(1.2米)。
在这一点上,它会注意到你叫
GetDouble
- 但是你要设定的返回值,达120万,这是无效的。
您可以验证这很容易地,一些记录。日志行添加到
GetTheDoubleCastToDecimal
,然后拆出从返回的
存根
通话code>电话:Console.WriteLine(以前存根);
VAR stubCall = canGetDecimal.Stub(OBJ => obj.GetTheDoubleCastToDecimal();
Console.WriteLine(存根后);
stubCall.Return(1.2米);
我强烈怀疑你会发现,无论你记录加入到扩展方法仍然登录以前存根之间以及存根后 - 这表明扩展方法的不的被嘲笑了。
道德:唐T试图模拟/存根扩展方法他们是不是多态;。他们只是静态方法,这将是相当棘手假冒他们不深的魔法,只有尝试假了真正的多态操作
I am able to stub a static extension method using Rhino Mocks but if I cast the return value to another type, I get an error. Why?
using Rhino.Mocks; public interface INumberGenerator { double GetDouble(); } static class NumberGeneratorExtensionMethods { public static double GetTheDouble(this INumberGenerator input) { return input.GetDouble(); } public static decimal GetTheDoubleCastToDecimal(this INumberGenerator input) { return (decimal) input.GetDouble(); } } class MockExample { public void TriggerTheError() { var stub = MockRepository.GenerateStub<INumberGenerator>(); // This works stub.Stub(obj => obj.GetTheDouble()).Return(1.2d); // This throws the error stub.Stub(obj => obj.GetTheDoubleCastToDecimal()).Return(1.2m); } }
Here is the error:
System.InvalidOperationException : Type 'System.Decimal' doesn't match the return type 'System.Double' for method 'INumberGenerator.GetDouble();'
解决方案Warning: this is really a suspicion more than anything else
The problem is that you're not really stubbing the extension methods at all - you're stubbing
GetDouble
in both cases.I haven't looked at the code for Rhino Mocks for a while, but I suspect that the
Stub
method is basically saying:
- Get ready for some calls on the mock!
- Call the delegate passed in as an argument
- Note which calls were made
That means you're effectively doing this:
canGetDecimal.Stub(ng => ng.GetDouble()).Return(1.2d); canGetDecimal.Stub(ng => (decimal) ng.GetDouble()).Return(1.2m);
At that point, it would notice that you called
GetDouble
- but then you're trying to set the return value to 1.2m, which is invalid.You could validate this pretty easily, with some logging. Add a log line to
GetTheDoubleCastToDecimal
and then split out theStub
call from theReturn
call:Console.WriteLine("Before Stub"); var stubCall = canGetDecimal.Stub(obj => obj.GetTheDoubleCastToDecimal(); Console.WriteLine("After Stub"); stubCall.Return(1.2m);
I strongly suspect you'll find that whatever logging you add into the extension method is still logged between "Before Stub" and "After Stub" - showing that the extension method isn't being mocked out.
Moral: don't try to mock/stub extension methods. They're not polymorphic; they're just static methods, and it would be pretty tricky to fake them without deep wizardry. Only try to fake out genuinely polymorphic operations.
这篇关于打桩静态扩展方法似乎犀牛制品工作,除非我投返回变量。为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!