除非我强制转换返回变量,否则在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"不匹配

除非我强制转换返回变量,否则在Rhino Mocks中Stubbing静态扩展方法似乎是可行的.为什么?

警告:这真的是一种怀疑

问题是,您根本就不是真正的存根扩展方法——在这两种情况下,您都是存根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字段的值即可。