2016-04-19 52 views
1

我有一個基類:單元測試,以驗證一個基類的方法被稱爲

public abstract class MyBaseClass 
{ 
    protected virtual void Method1() 
    {  
    } 
} 

和派生類:

public class MyDerivedClass : MyBaseClass 
{ 
    public void Method2() 
    { 
     base.Method1(); 
    } 
} 

我想要寫一個單元測試用於Method2驗證它在基類上調用Method1。我使用Moq作爲我的嘲笑圖書館。這可能嗎?

我遇到了一個相關的SO鏈接:

Mocking a base class method call with Moq

其中第2個答案表明,它可以通過設置CallBase屬性爲true模擬對象上實現。但是,如何能夠調用基類方法(上例中的Method1)並不明確。

感謝您對此的任何幫助。

+2

爲什麼一個要求,即基本方法被調用?如果你嘲笑它,所有你正在驗證_mock_調用基本方法。你只是驗證'base.'語法是否工作,或者你是否需要繼承的類來調用基類? –

+2

另外,您應該只測試_results_是否正確。測試使用特定的_implementation_通常表示設計不好。 –

+1

基本方法是否有可驗證的副作用? –

回答

10

單元測試應該驗證行爲,不實現。有幾個方面的原因:

  • 結果的目標,而不是你怎麼弄結果
  • 測試結果可以讓你提高執行,而無需重新編寫測試
  • 實現更難嘲笑

可能能夠把鉤子或創建驗證基方法被稱爲嘲笑,但你真的關心如何答案已經實現,或者你在意那個答案是對不對

如果您需要的特定實現具有可驗證的副作用,那麼是您應該驗證的內容。

+2

好的答案(+1)...對於OP來說更重要的事情是:如果您不能驗證被測方法的預期行爲,那麼基類中的未來更改可能會破壞CUT行爲沒有和通知... –

3

從派生類的角度嘲笑基類是不可能的。在你的簡單例子中,我會建議兩個選項之一。

選項1:如果MyDerivedClass確實不應該在意什麼MyBaseClass是否合格,那麼請使用依賴注入!耶抽象!

public class MyClass 
{ 
    private readonly IUsedToBeBaseClass myDependency; 

    public MyClass(IUsedToBeBaseClass myDependency){ 
     _myDependency = myDependency; 
    } 

    public void Method2() 
    { 
     _myDependency.Method1(); 
    } 
} 

別處在測試的土地......

[TestClass] 
public class TestMyDependency { 
    [TestMethod] 
    public void TestThatMyDependencyIsCalled() { 
     var dependency = new Mock<IUsedToBeBaseClass>(); 
     var unitUnderTest = new MyClass(dependency.Object); 
     var unitUnderTest.Method2(); 
     dependency.Verify(x => x.Method1(), Times.Once); 
    } 
} 

選項2:倘若MyDerivedClass需要知道什麼MyBaseClass在做什麼,然後測試MyBaseClass是做正確的事

在替代試驗土地...

[TestClass] 
public class TestMyDependency { 
    [TestMethod] 
    public void TestThatMyDependencyIsCalled() { 
     var unitUnderTest = new MyDerivedClass(); 
     var unitUnderTest.Method2(); 
     /* verify base class behavior #1 inside Method1() */ 
     /* verify base class behavior #2 inside Method1() */ 
     /* ... */ 
    } 
} 
+0

謝謝你的信息反應。 – aw1975

+0

歡迎@ aw1975 –

1

你所描述的不是測試你的代碼,而是測試語言的行爲。這很好,因爲這是確保語言按照我們認爲的方式行事的好方法。當我學習時,我曾經寫過很多小控制檯應用程序。我希望我知道單元測試,因爲這是更好的方法。

但是,一旦您測試了它並確認語言的行爲符合您的期望,我就不會繼續爲此編寫測試。你可以測試你的代碼的行爲。

這裏是一個真正簡單的例子:

public class TheBaseClass 
{ 
    public readonly List<string> Output = new List<string>(); 

    public virtual void WriteToOutput() 
    { 
     Output.Add("TheBaseClass"); 
    } 
} 

public class TheDerivedClass : TheBaseClass 
{ 
    public override void WriteToOutput() 
    { 
     Output.Add("TheDerivedClass"); 
     base.WriteToOutput(); 
    } 
} 

單元測試

[TestMethod] 
    public void EnsureDerivedClassCallsBaseClass() 
    { 
     var testSubject = new TheDerivedClass(); 
     testSubject.WriteToOutput(); 
     Assert.IsTrue(testSubject.Output.Contains("TheBaseClass")); 
    } 
+0

好點。謝謝。 – aw1975

相關問題