除非我强制转换返回变量,否则在Rhino Mocks中Stubbing静态扩展方法似乎是可行的.为什么?
本文关键字:扩展 方法 静态 Stubbing 似乎是 为什么 Mocks Rhino 转换 非我 返回 | 更新日期: 2023-09-27 18:22:41
我可以使用Rhino Mocks存根一个静态扩展方法,但如果我将返回值强制转换为另一种类型,我会得到一个错误。为什么?
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);
}
}
错误如下:
System.InvalidOperationException:类型"System.Decimal"与方法"INumberGenerator.GetDouble();"的返回类型"System.Double"不匹配
警告:这真的是一种怀疑
问题是,您根本就不是真正的存根扩展方法——在这两种情况下,您都是存根GetDouble
。
我已经有一段时间没有看Rhino Mocks的代码了,但我怀疑Stub
方法基本上是在说:
- 准备好在mock上进行一些调用
- 调用作为参数传入的委托
- 记下打了哪些电话
这意味着你正在有效地做到这一点:
canGetDecimal.Stub(ng => ng.GetDouble()).Return(1.2d);
canGetDecimal.Stub(ng => (decimal) ng.GetDouble()).Return(1.2m);
这时,它会注意到您调用了GetDouble
,但随后您试图将返回值设置为1.2米,这是无效的。
通过一些日志记录,您可以很容易地验证这一点。向GetTheDoubleCastToDecimal
添加日志行,然后将Stub
调用与Return
调用分离:
Console.WriteLine("Before Stub");
var stubCall = canGetDecimal.Stub(obj => obj.GetTheDoubleCastToDecimal();
Console.WriteLine("After Stub");
stubCall.Return(1.2m);
我强烈怀疑您会发现,添加到扩展方法中的任何日志记录仍然记录在"Before Stub"answers"After Stub"之间,这表明扩展方法并没有被嘲笑。
道德:不要尝试mock/stub扩展方法。它们不是多态的;它们只是静态方法,如果没有深层的魔法,伪造它们将非常棘手。只尝试伪造真正的多态操作。
在没有任何框架的情况下,可以存根扩展方法或任何其他静态方法。这需要一点额外的负担。
public static class MyExtensions
{
public static Func<int,int, int> _doSumm = (x, y) => x + y;
public static int Summ(this int x, int y)
{
return _doSumm(x, y);
}
}
它允许您替换实现。您只需更改_doSumm
字段的值即可。