[英]Moq It.Is<> not matching
這段代碼:
hub.MockedUserRepository.Setup(r => r.Update(It.IsAny<ControllUser>()))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
會打印
NULL = True
所以我在想使用這種匹配會抓住它:
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();
但事實並非如此。
為什么?
通過查看It
的源代碼, 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();
使用非空ControllUser
(例如,正在測試的方法)執行Update
方法時,不會觸發回調。 它根本不符合標准,因為它不是空的。 您也會看到驗證失敗。
要解決此問題,可以內聯zombieDisconnectParameterMatcher
變量,或使其成為表達式類型變量(例如, Expression<Func<...>>
)。 后者將確保代碼不被執行,但被視為模擬框架可以推理的表達式('是使用Zombies[0].ConnectionId == null
?來調用Update
)。
這取決於ControllUser
實例的實例化方式。 如果您在模擬中引用的實例不是測試代碼中引用的實際實例,則Setup
將失敗。 您需要確保測試代碼中引用的ControllUser
實例與測試代碼中的對象相同 。 如果不是,您將必須使用It.IsAny<ControllUser>()
和回調測試它,如您的第一個示例所示。 如果沒有看到您正在測試的更多代碼,很難肯定地說。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.