起订量It.Is <>不匹配
问题描述:
此代码:起订量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();
但它没有。
为什么?
答
通过查看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
?)。
答
这取决于如何实例化ControllUser
实例。如果您在模拟中引用的实例不是被测代码中提到的实际实例,则Setup
将会失败。您需要确保在测试代码中提到的ControllUser
的实例是与测试代码中相同的对象。如果不是,您将不得不使用It.IsAny<ControllUser>()
和回调进行测试,如第一个示例所示。如果没有看到更多您正在测试的代码,很难确定地说出来。
@Caramiriel先生,我向你敬礼。 – fernandoespinosa 2014-04-07 18:15:16