2013-06-20 41 views
1

我創建了一個按順序調用moq的擴展方法(見下文),每個this SO answer模擬回調訂單邊緣案例錯誤

一個例子的使用情況是:

mock.setup.CallbackSequence(new List{h,e,l,l,o}) 

在那裏我通過hello到我SUT,並期望以人物。

問題是這樣的情況:

mock.setup.CallbackSequence(new List{h,e,l,l,o,X}) 

,我通過hello。即使由於動態聲明本質而失敗(X從未發送,但我們永遠不知道),它仍會通過。我能想到的解決這個問題的唯一方法是添加一個

mock.Verify(setupmethod, Times.Exactly(list.Count)) 

然而,回調設置和驗證兩個不同的地方都做了,所以它會落在擴展方法的消費者實現這個缺陷。我想避免把它放在他們身上,因爲它肯定會失敗......建議?

public static ICallbackResult CallbackSequence<TMockType, T1, T2>(this ISetup<TMockType> mockSetup, IList<T1> sequencedList) where TMockType : class 
{ 
    //Refactor: Does not fail if it does not reach the end, only if out of order and/or too long 
    var index = 0; 
    return mockSetup.Callback((T1 t1, T2 t2) => 
    { 
    if(index >= sequencedList.Count) 
     Assert.That(false, "Sequenced list attempted to access index out of bounds. Count is " + sequencedList.Count + "; index is " + index + "; value being checked is " + t1); 
    var currentItemInSequence = sequencedList[index]; 
    Assert.That(t1, Is.EqualTo(currentItemInSequence), String.Format("Failed sequence at position{0}", index)); 
    index++; 
    }); 
} 

編輯

我能想到的,可能工作的唯一事情是返回,消費者應該在最後調用自定義對象:

var sequenceVerifier = ...CallbackSequence(); 
//Do Stuff 
sequenceVerifier.VerifySequence(); 

這是仍然不是最優的,因爲這給人的印象是,直到VerifySequence被調用時纔會驗證,但它只會執行邊緣情況....除非我不在回調中聲明,而只是在結束???????這可能工作,思想?

回答

1

在與一些同事交談之後,我們提出了一種雙重方法,將其留給實施者。

選項1

返回SequenceVerifier必須有一個名爲其VerifySequenceCalls方法

選項2

通過我的行動統一到一個輔助方法,以便它可以安裝,行爲,然後驗證邊緣情況

我可以在我的第二個選項中使用SequenceVerifier。然後,消費者如何讓他們的代碼看起來如此。

public static MockSequenceVerifier<T1> CallbackInOrderOfSequence<TMockType, T1, T2>(this ISetup<TMockType> mockSetup, IList<T1> sequencedList) where TMockType : class 
{ 
    var mockSequenceVerifier = new MockSequenceVerifier<T1>(sequencedList); 
    mockSetup.Callback((T1 t1, T2 t2) => mockSequenceVerifier.UpdateSequence(t1)); 
    return mockSequenceVerifier; 
} 

public static void VerifySequenceAfterActionPerformed<TMockType, T1, T2>(this ISetup<TMockType> mockSetup, IList<T1> sequencedList, Action actionToPerform) where TMockType : class 
{ 
    var verifier = CallbackInOrderOfSequence<TMockType, T1, T2>(mockSetup, sequencedList); 
    actionToPerform(); 
    verifier.VerifySequence(); 
} 

public class MockSequenceVerifier<T> 
{ 
    private IList<T> SequenceToVerifyAgainst { get; set; } 
    private IList<T> ActualSequence { get; set; } 

    public MockSequenceVerifier(IList<T> sequenceToVerifyAgainst) 
    { 
    SequenceToVerifyAgainst = sequenceToVerifyAgainst; 
    ActualSequence = new List<T>(); 
    } 

    public void VerifySequence() 
    { 
    ActualSequence.IsEqualTo(SequenceToVerifyAgainst); 
    } 

    public void UpdateSequence(T item) 
    { 
    ActualSequence.Add(item); 
    } 
} 
+0

尚未驗證此答案的正確性,但我相信成爲一名自學者是好的。 –

+0

@KenKin我在驗證其正確性後添加了代碼 –