2013-03-12 35 views
7

此代碼:起訂量It.Is <>不匹配

hub.MockedUserRepository.Setup(r => r.Update(It.IsAny<ControllUser>())) 
         .Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null))) 
         .Verifiable(); 

將打印

NULL =真

所以我用這個匹配會抓住它想:

var zombieDisconnectParameterMatcher = It.Is<ControllUser>(x => x.Zombies[0].ConnectionId == null); 
hub.MockedUserRepository.Setup(r => r.Update(zombieDisconnectParameterMatcher)) 
         .Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null))) 
         .Verifiable(); 

但它沒有。

爲什麼?

回答

9

通過查看source code of It,它與表達式樹有關。我喜歡這個問題;他們可能會很困惑。如果你想看看下面的方法定義:

public static TValue It.Is<TValue>(Expression<Func<TValue, bool>> match) 
{ 
     return Match<TValue>.Create(
       value => match.Compile().Invoke(value), 
       () => It.Is<TValue>(match)); 
} 

public static T Match.Create<T>(Predicate<T> condition, Expression<Func<T>> renderExpression) 
{ 
     // ... 
     return default(T); 
} 

,如果您執行以下行:

var zombieDisconnectParameterMatcher = It.Is<ControllUser>(x => x.Zombies[0].ConnectionId == null); 

然後It.Is<ControllUser>()將嘗試呼叫被叫Match.Create<ControllUser>()方法,它返回的默認ControllUser。我假設ControllUser是一類,因此zombieDisconnectParameterMatcher將是null。你應該能夠通過調試器看到這一點。那麼究竟是什麼你打電話是:

hub.MockedUserRepository.Setup(r => r.Update(null)) 
    .Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null))) 
    .Verifiable(); 

與執行Update方法當一個非空ControllUser(從正在例如測試的方法),回調就不會觸發。它不符合標準,因爲它不爲空。你也會看到驗證失敗。

要解決此問題,請嵌入zombieDisconnectParameterMatcher變量,或使其成爲表達式類型變量(例如,Expression<Func<...>>)。後者將確保代碼不被執行,但被視爲模擬框架可以推理的表達式('Update被稱爲Zombies[0].ConnectionId == null?)。

+0

@Caramiriel先生,我向你敬禮。 – fernandoespinosa 2014-04-07 18:15:16

1

這取決於如何實例化ControllUser實例。如果您在模擬中引用的實例不是被測代碼中提到的實際實例,則Setup將會失敗。您需要確保在測試代碼中提到的ControllUser的實例是與測試代碼中相同的對象。如果不是,您將不得不使用It.IsAny<ControllUser>()和回調進行測試,如第一個示例所示。如果沒有看到更多您正在測試的代碼,很難確定地說出來。

相關問題