2013-04-04 4 views
5

Ich habe ein Klasse-Setup auf die folgende Weise:Unterstützt Microsoft Fakes abstrakte Methoden auf einem Shim?

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

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

    public abstract WhatIWantToShim(); 
} 

Was ich will, wie so den WhatIWantToShim auf dem ShimFooClass gesetzt tun:

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

ich RandomMethod ganz gut,

einstellen

Es scheint jedoch, dass die generierte ShimFooClass die WhatIWantToShim-Eigenschaft für die AllInstances-Eigenschaft der ShimFooClass nicht erstellt.

Ich habe mir http://msdn.microsoft.com/en-us/library/hh549176.aspx#bkmk_shim_basics angesehen, aber ich sehe dort nichts über abstrakte Methoden. Die einzige Sache, auf die ich referenziere, die nicht unterstützt wird, sind Finalizer. Weiß jemand, was hier vor sich geht und ob dieses Szenario unterstützt wird?

+0

Können Sie eine Methode erstellen, die die Eigenschaft festlegt? – RedJandal

+0

Ihnen nicht folgend, gibt es keine Eigenschaft für die abstrakte Methode, die für die Shim-Klasse erstellt wurde. Das ist das Problem. –

Antwort

4

Ahhh .... Bummer

Schnittstellen und abstrakte Methoden. Stubs stellen Implementierungen von Schnittstellen und abstrakte Methoden bereit, die beim Testen verwendet werden können. Shims können Interfaces und abstrakte Methoden nicht instrumentieren, weil sie keine Methodenkörper haben.

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

Update: was ist allerdings die Shim stubbing getan werden kann.

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

Da die Scheibe der WhatIWantToShim Methode Umleiten und der Stummel kann nicht umgehen kann, einfach eine neue Instanz der Stub-Klasse erstellen und den Umweg Handler für die abstrakte Methode gesetzt. (Hinweis: die 01 am Ende von WhatIWantToShim wurde automatisch für mich hinzugefügt, als die Fakes in meinem tatsächlichen Code erzeugt wurden).

Dann übergeben Sie einfach den instanziierten Stub an den Konstruktor der Shim-Klasse und shim weg wie benötigt.

0

Ich antworte hier, weil ich ziemlich sicher bin, dass die andere Antwort die Frage nicht beantwortet, und so dass zukünftige Suchen nützliche Informationen zurückgeben.

Erstens können Sie Schnittstellen nicht shim. Eine abstrakte Methode entspricht einer Schnittstelle. Außerdem gibt es keinen Grund dazu.

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

Das obige ist eine vereinfachte Version einer vorherigen Antwort und ruft einfach die Aktion auf, die Sie gerade zugewiesen haben. Dies ist wahrscheinlich nicht Ihre Absicht.

Denken Sie daran, warum Sie shim. Wenn Sie die Auswirkungen eines Methodenaufrufs innerhalb einer von Ihnen getesteten Methode vermeiden möchten, müssen Sie die Option shim verwenden. Die abstrakte Methode kann keinen Körper haben und kann daher nichts beeinflussen. Das einzige Mal, wo dies nützlich wäre, ist in einer Kindklasse, wo die Shim für Sie verfügbar wäre.

Die einzige Situation, in der Sie möglicherweise ein Problem haben, ist, wenn eine dritte Klasse eine Instanz der abstrakten Klasse heimlich hält und sie mit der Kindklasse instanziiert. Du kannst das nicht vortäuschen. Es ist jedoch ein schreckliches Design; Die Instanz sollte von einer Methode kommen (die Sie shim) oder übergeben (Weil DI ist eine gute Sache!) oder aber die Abstraktion ist wertlos, und Sie können die Instanz auch als Kindtyp deklarieren, da Sie die Abstraktion in keiner Weise verwenden.

Verwandte Themen