2008-12-24 67 views
2
稱爲

假設我有下面的類:驗證保護的抽象方法是使用起訂量

public class TestBase 
{ 
    public bool runMethod1 { get; set; } 

    public void BaseMethod() 
    { 
    if (runMethod1) 
     ChildMethod1(); 
    else 
     ChildMethod2(); 
    } 

    protected abstract void ChildMethod1(); 
    protected abstract void ChildMethod2(); 
} 

我也有類

public class ChildTest : TestBase 
{ 
    protected override void ChildMethod1() 
    { 
    //do something 
    } 

    protected override void ChildMethod2() 
    { 
    //do something completely different 
    } 

} 

我使用起訂量,我想寫當我調用BaseMethod()並且runMethod1爲true時,會調用驗證ChildMethod1()的測試。是否可以使用Moq創建TestBase實現,調用BaseMethod()並驗證Moq實現上是否調用了ChildMethod?

[Test] 
public BaseMethod_should_call_correct_child_method() 
{ 
    TestBase testBase; 

    //todo: get a mock of TestBase into testBase variable 

    testBase.runMethod1 = true; 

    testBase.BaseMethod(); 

    //todo: verify that ChildMethod1() was called 

} 
+0

這個例子看起來像你正在測試CLR而不是你自己的代碼。這是你真正想要的嗎? – 2008-12-24 02:19:19

+0

實際代碼更復雜。我根據對象的狀態在子類中調用不同的方法。我只想在這裏寫一個簡單的例子,但我會更新它,所以還有更多的東西需要測試。 – 2008-12-24 02:24:48

回答

5

您還可以設置的期望/設置爲覈查,離不開嚴格的Mock:

//expect that ChildMethod1() will be called once. (it's protected) 
    testBaseMock.Protected().Expect("ChildMethod1") 
    .AtMostOnce() 
    .Verifiable(); 

    ... 

    //make sure the method was called 
    testBase.Verify(); 

編輯 這句法不會起訂量的當前版本。請參閱this question如何做到這一點至少4.0.10827

0

這看起來像你測試的行爲,而不是公共接口。如果這是有意的,那麼你可以看看測試私人成員的建議。

「是否可以使用Moq創建TestBase的實現,調用BaseMethod()並驗證Moq實現上是否調用了ChildMethod?」

這是可能的。但是,你會測試模擬對象,而不是真正的對象。

  1. 是否descendatn類返回比基類不同的值:可能會引導你在正確的方向

    兩個問題?如果是這樣,你可以測試並忽略implimentation細節(也使得重構更容易)。

  2. 後代類是否調用不同的方法或不同的依賴關係?如果是這樣,你可以檢查依賴關係。

1

這是一個黑客,但如何創建一個TestBase的子類,使ChildMethod1和ChildMethod公開,然後Moqing呢?

4

我想出瞭如何做到這一點。你可以用Moq來嘲弄受保護的方法,並且通過嚴格的模擬,你可以驗證它們是否被調用。現在我可以測試基類而不必創建任何子類。

[Test] 
public BaseMethod_should_call_correct_child_method() 
{ 
    //strict mocks will make sure all expectations are met 
    var testBaseMock = new Mock<TestBase>(MockBehavior.Strict); 

    //expect that ChildMethod1() will be called once. (it's protected) 
    testBaseMock.Protected().Expect("ChildMethod1") 
    .AtMostOnce(); 

    var testBase = testBaseMock.Object; 

    testBase.runMethod1 = true; 
    testBase.BaseMethod(); 

    //make sure the method was called 
    testBase.VerifyAll(); 
}