2011-10-21 28 views
7

我目前運行測試,看起來像以下代碼:如何使用起訂量來測試要求受保護的助手

// In Blah.cs 
public class ClassUnderTest 

{ 

    public bool MethodUnderTest() 

    { 

     // Do a bunch of stuff... 

     return HelperMethod(); 

    } 



    protected virtual bool HelperMethod() 

    { 

     bool success = false; 

     // Proprietary Hardware Access. 

     // Database Calls. 

     // File System Modifications. 

     return success; 

    } 

} 


// In TestBlah.cs 

public class TestStub : ClassUnderTest 

{ 

    public bool HelperMethodReturnValue; 



    protected override bool HelperMethod() 

    { 

     return HelperMethodReturnValue; 

    } 

} 



[TestClass] 

public class TestingClass 

{ 

    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsTrue() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = true; 

     Assert.IsTrue(stub.MethodUnderTest()); 

    } 



    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = false; 

     Assert.IsFalse(stub.MethodUnderTest()); 

    } 

} 

上面看起來不錯的簡單的事情,但是存根類獲取成倍更大,更復雜的迅速。 我想用Moq替換存根類。然而,這不會編譯,因爲由於某種原因,我不能在受保護的方法上設置返回值。

[TestMethod] 

public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

{ 

    var mockClass = new Mock<ClassUnderTest>(); 
    mockClass.Protected().Setup("HelperMethod").Returns(false); 

    Assert.IsFalse(mockClass.Object.MethodUnderTest()); 

} 

任何人都知道我該怎麼做呢?我可以用moq來做這個嗎?

+5

這裏有些東西似乎不對...你不嘲笑你的SUT,你嘲笑它的依賴。 –

+0

是的,實際上Yojin嘲笑SUT來替換應該保持分開的SUT的一部分,而不是以受保護的輔助方法。 – Matthias

回答

23

看着moq source code我想猜想您需要顯式調用通用版本的安裝程序。非通用版本似乎用於void方法。所以請嘗試

mockClass.Protected().Setup<bool>("HelperMethod").Returns(false); 

除此之外,我建議重新考慮您的班級設計。如果HelperMethod()正在做這麼多事情,那麼值得將它作爲依賴注入到ClassUnderTest中的自己的類值得。測試一個模擬對象,而不是使用一個模擬對象來測試「真實」的東西,這不是模擬框架(至少不是首先)。

4

受保護的方法不是隔離依賴關係的好方法,但有時會出現,尤其是在適應遺留代碼的可測試性時。避免笨拙的基於字符串的Moq語法的一個選項是使方法'受保護的內部'(如果不打算在其他程序集的正常使用中重寫它),則使該方法爲'受保護的內部'。然後,您使用組件上的InternalsVisibleTo揭露該方法。這有點駭人聽聞,但爲此目的使用受保護的方法已經有點黑客了。在某些方面,我更喜歡'內部'方法,因爲它清楚地表明這是一個你不應該使用的後門方法(除了測試),而不是你可能期望在正常情況下覆蓋的受保護方法用法。