6

I have a class setup in the following manner:

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

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

    public abstract WhatIWantToShim();
}

What I want to do is set the WhatIWantToShim on the ShimFooClass like so:

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

I can set RandomMethod just fine,

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

However, it appears that the generated ShimFooClass does not create the WhatIWantToShim property on the AllInstances property of the ShimFooClass.

I've looked at http://msdn.microsoft.com/en-us/library/hh549176.aspx#bkmk_shim_basics but I don't see anything there about abstract methods. The only thing I see referenced that is not supported is finalizers. Anybody know what is going on here and if this scenario is supported?

4

2 回答 2

5

啊……无赖

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

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.");
}

由于 shim 无法处理 WhatIWantToShim 方法的迂回,而存根可以,只需创建存根类的新实例并为抽象方法设置迂回处理程序。(注意:WhatIWantToShim 末尾的 01 标记是在我的实际代码中生成 Fakes 时自动为我添加的)。

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

于 2013-04-04T22:55:54.960 回答
1

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

首先,您不能填充接口。抽象方法等价于接口。此外,没有理由这样做。

{
    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.");
}

以上是先前答案的简化版本,将简单地调用您刚刚分配的操作。这可能不是你的意图。

记住为什么你垫片。当您想避免在您正在测试的方法中的方法调用的影响时,您可以使用 shim。抽象方法可以没有主体,因此不会影响任何东西。唯一有用的是在子类中,首先您可以使用 shim。

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

于 2013-10-08T22:28:17.233 回答