除非我转换返回变量,否则在Rhino Mocks中使用stubbing静态扩展方法似乎有效。为什么?

时间:2013-07-15 19:10:27

标签: c# rhino-mocks

我能够使用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'不匹配

2 个答案:

答案 0 :(得分:10)

警告:这真的是一种怀疑

问题是你根本没有真正存根扩展方法 - 在这两种情况下你都是GetDouble

我暂时没有查看Rhino Mocks的代码,但我怀疑 Stub方法基本上是这样说的:

  • 准备好对模拟进行一些调用!
  • 将作为参数传入的委托称为
  • 请注意拨打了哪些电话

这意味着你有效地做到了这一点:

canGetDecimal.Stub(ng => ng.GetDouble()).Return(1.2d);
canGetDecimal.Stub(ng => (decimal) ng.GetDouble()).Return(1.2m);

此时,它会注意到你调用了GetDouble - 但是你试图将返回值设置为1.2m,这是无效的。

您可以通过一些日志记录轻松验证这一点。将日志行添加到GetTheDoubleCastToDecimal,然后从Stub来电中分出Return来电:

Console.WriteLine("Before Stub");
var stubCall = canGetDecimal.Stub(obj => obj.GetTheDoubleCastToDecimal();
Console.WriteLine("After Stub");
stubCall.Return(1.2m);

我强烈怀疑你会发现你添加到扩展方法中的任何日志记录仍然记录在“Before Stub”和“After Stub”之间 - 显示扩展方法不是被模拟进行。

道德:不要尝试模拟/存根扩展方法。它们不是多态的;它们只是静态方法,在没有深刻魔法的情况下伪造它们会非常棘手。只是试图伪造真正的多态操作。

答案 1 :(得分:1)

有可能存在扩展方法或任何其他静态方法而没有任何框架。这需要一点额外的费用。

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字段的值。