Microsoft Fakes是否支持垫片上的抽象方法?

时间:2013-04-04 22:27:07

标签: c# abstract microsoft-fakes

我按以下方式设置了课程:

public abstract FooClass {
    public FooClass() {
        // init stuff;
    }

    public void RandomMethod() {
        // do stuff;
    }

    public abstract WhatIWantToShim();
}

我想要做的是在ShimFooClass上设置WhatIWantToShim,如下所示:

ShimFooClass.AllInstances.WhatIWantToShim = () => Boo();

我可以设置RandomMethod就好了,

ShimFooClass.AllInstances.RandomMethod = () => CalculatePi();

但是,生成的ShimFooClass似乎不会在ShimFooClass的AllInstances属性上创建WhatIWantToShim属性。

我看过http://msdn.microsoft.com/en-us/library/hh549176.aspx#bkmk_shim_basics,但我没有看到任何有关抽象方法的内容。我看到的唯一不支持的是终结器。有人知道这里发生了什么,是否支持这种情况?

2 个答案:

答案 0 :(得分:4)

唉唉....长号

  

接口和抽象方法。 Stubs提供了可用于测试的接口和抽象方法的实现。垫片不能检测接口和抽象方法,因为它们没有方法体。

http://msdn.microsoft.com/en-us/library/hh549175(v=vs.110).aspx

更新:虽然可以做什么是破坏垫片。

using (ShimsContext.Create())
{
    bool wasAbstractMethodCalled = false;
    var targetStub = new StubFooClass()
    {
        WhatIWantToShim01 = () => wasAbstractMethodCalled = true
    };
    var targetShim = new ShimFooClass(targetStub);
    targetShim.AllInstances.RandomMethod = () => CalculatePi();
    FooClass  target = targetShim.Instance;
    target.WhatIWantToShim();
    Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called.");
}

由于垫片无法处理绕过WhatIWantToShim方法和存根的方法,只需创建存根类的新实例并为抽象方法设置绕行处理程序。 (注意:在我的实际代码中生成伪造时,我自动添加了标记在WhatIWantToShim末尾的01)。

然后将实例化的存根传递给shim类的构造函数,并根据需要进行填充。

答案 1 :(得分:0)

我在这里回复是因为我很确定其他答案没有回答这个问题,以便将来的搜索会返回有用的信息。

首先,你不能使用shim接口。抽象方法相当于一个接口。此外,没有理由。

{
    bool wasAbstractMethodCalled = false;
    var targetStub = new StubFooClass()
    {
        WhatIWantToShim01 = () => wasAbstractMethodCalled = true
    };
    ShimFooClass.AllInstances.RandomMethod = @class => targetStub.CalculatePi();
    targetStub.WhatIWantToShim();
    Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called.");
}

以上是上一个答案的简化版本,只会调用您刚刚分配的操作。这可能不是你的意图。

记住你为什么要垫片。当您想要避免在正在测试的方法中的方法调用的影响时,您可以进行填充。抽象方法没有主体,因此不会影响任何东西。唯一有用的时间是在儿童班,一开始就可以使用垫片。

您可能遇到问题的唯一情况是,第三个类是秘密持有抽象类的实例并使用子类实例化它。你无法假装。然而,这是一个糟糕的设计;实例应该来自某个方法(你可以填充)或传入(因为DI是一件好事!)或者抽象是没有价值的,你也可以将实例声明为子类型,因为你不以任何方式使用抽象。