2017-09-03 59 views
0

我最近開始使用Typemock,並查看了至少六個現有線程,但似乎無法找到我確切問題的答案。使用Typemock僞造每個父代的所有實例

我有一個從B派生出來的類C,它本身是從A派生出來的。C的實例就是我需要測試的,因此需要是真實的。但作爲C來自乙派生(或間接A),我需要當我創建C.

的實例

見下面這兩個類完全自動僞造:

class A 
{ 
    protected int methodA() 
    { 
     return 1; 
    } 
} 

class B : A 
{ 
    protected int methodB() 
    { 
     return 5; 
    } 
} 

class C : B 
{ 
    public int methodC() 
    { 
     return methodA() * methodB(); 
    } 
} 

class Test 
{ 
    public Test() 
    { 
     A fake_A = Isolate.Fake.AllInstances<A>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored); 
     Isolate.NonPublic.WhenCalled(fake_A, "methodA").DoInstead((MethodCallContext ctx) => 
      { 
       return 2; 
      } 
     ); 

     B fake_B = Isolate.Fake.AllInstances<B>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored); 
     Isolate.NonPublic.WhenCalled(fake_B, "methodB").DoInstead((MethodCallContext ctx) => 
      { 
       return 10; 
      } 
     ); 

     C c = new C(); // Would expect A and B to be faked automatically since I've faked all instances above. 
     int method_c_val = c.methodC(); // I get back 5, but what I need returned is 20. 
    } 
} 

這是的一個非常簡化的版本我正面臨的問題。這不僅僅是在父類中僞造一個或兩個方法的行爲。整個家長層面都需要僞造。所以A和B都需要完全僞造,而不是部分僞造。

一個我已經看了看線程是這一個,但在有指向一個地址的答案,不再可用:

https://www.typemock.com/answers/11613/mocking-all-instances-of-a-base-class

+1

模擬部分系統測試的應用程序非常糟糕,嘲諷**單個對象的**方面**聽起來像一個可怕的想法。如果你真的必須這樣做,我建議你重構一個_composition pattern_ – MickyD

+0

請你詳細說明爲什麼這是一個可怕的想法?鏈接到文章,討論,另一個線程,博客,什麼(什麼)來支持你的陳述?不是說我不相信你,但是一些例子會走很長的路...... – Ash

+1

因爲你的班不是爲此目的而設計的。你所擁有的只是一組沒有_design pattern_的方法集合。推薦由「四人幫」設計模式書。祝你好運 – MickyD

回答

2

我不熟悉typemock,但如果您無法獲得答案,控制了有問題的代碼並能夠對其進行修改,我可以提出另一種可能的解決方法。

製作問題virtual中的方法,使派生類能夠覆蓋它們。

class A 
{ 
    protected virtual int methodA() 
    { 
     return 1; 
    } 
} 

class B : A 
{ 
    protected virtual int methodB() 
    { 
     return 5; 
    } 
} 

class C : B 
{ 
    public int methodC() 
    { 
     return methodA() * methodB(); 
    } 
} 

爲了隔離測試methodC您可以創建由C重寫問題的方法得出的stub類d。

class D : C 
{ 
    protected override int methodA() 
    { 
     return 2; 
    } 

    protected override int methodB() 
    { 
     return 10; 
    } 
} 

由於測試的結果與預期的一樣。

[TestClass] 
public class Test 
{ 
    [TestMethod] 
    public void TestMethodC() 
    { 
     //Arrange 
     var expected = 20; 
     var c = new D(); 

     //Act 
     int actual = c.methodC(); 

     //Assert 
     Assert.AreEqual(expected, actual); 
    } 
} 

我認爲與typemock你需要做的通過僞造C只有隔離有問題的兩個依賴的方法,使該方法測試被稱爲自然類似的東西。但是我對這個框架並不熟悉。

+0

是的,這可以在你剛開始提到的環境中工作,但即使如此,它也需要很多代碼來創建(本質上)一種解決方法。這只是一個非常簡單的例子。即使我可以編輯A和B的代碼(我不能),但A和B的實際類是怪物。爲了做一個真正的隔離測試,我必須在每個課程中提供更多的方法。這就是Typemock進來的地方。它允許我將所有方法(遞歸地)僞裝成它們的默認原始值,並且我可以讓我的模擬在特定位置展示自定義行爲,例如方法。 – Ash

2

由於@Nkosi建議你可以使用:

C c = Isolate.Fake.Instance<C>(Memebers.CallOriginal); 
Isoalte.NonPublic.WhenCalled(c,"methodA").WillReturn(2); 
Isoalte.NonPublic.WhenCalled(c,"methodB").WillReturn(10); 

你假的C對象,但它仍然方法調用原始的實現(如果需要),而你只假冒的問題的方法。

+0

我編輯了我的問題。基本上,這不僅僅是僞造兩種方法行爲的問題......這只是一個例子,證明我已經嘗試過的方法(使用fakeAll)不起作用。我面臨的實際情況相當複雜,我需要整個A和B的僞造,而不僅僅是部分。 – Ash

+0

是的,但這取決於你想要測試什麼。在這種情況下,從基類繼承的方法由對象C調用,而不是由A或B調用,因此僞造它們,並且它們的方法不涉及C對象。 –