[英]Moq It.Is<> not matching
This code: 这段代码:
hub.MockedUserRepository.Setup(r => r.Update(It.IsAny<ControllUser>()))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
Will print 会打印
NULL = True
NULL = True
So i am thinking using this matching will catch it: 所以我在想使用这种匹配会抓住它:
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();
But it does not. 但事实并非如此。
Why? 为什么?
By looking at the source code of It
, it has to do with expression trees. 通过查看
It
的源代码, It
与表达式树有关。 I like the question; 我喜欢这个问题; they can be quite puzzling.
他们可能很令人费解。 If you would take a look at the following method definitions:
如果您要查看以下方法定义:
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);
}
If you would execute the following line: 如果您要执行以下行:
var zombieDisconnectParameterMatcher = It.Is<ControllUser>(x => x.Zombies[0].ConnectionId == null);
Then It.Is<ControllUser>()
will try to call a method called Match.Create<ControllUser>()
, which returns the default of ControllUser
. 然后
It.Is<ControllUser>()
将尝试调用名为Match.Create<ControllUser>()
,该方法返回默认的ControllUser
。 I assume ControllUser
is a class and therefore zombieDisconnectParameterMatcher
will be null
. 我假设
ControllUser
是一个类,因此zombieDisconnectParameterMatcher
将为null
。 You should be able to see this with the debugger. 您应该能够通过调试器看到这一点。 So what actually you're calling is:
所以你实际上是在呼唤:
hub.MockedUserRepository.Setup(r => r.Update(null))
.Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
.Verifiable();
When executing the Update
method with a non-null ControllUser
(from the method that is being tested for example), the callback will not trigger. 使用非空
ControllUser
(例如,正在测试的方法)执行Update
方法时,不会触发回调。 It simply doesn't match the criteria since it's not null. 它根本不符合标准,因为它不是空的。 You would see the verification fail, also.
您也会看到验证失败。
To resolve this issue, either inline the zombieDisconnectParameterMatcher
variable, or make it an expression typed variable (eg. Expression<Func<...>>
). 要解决此问题,可以内联
zombieDisconnectParameterMatcher
变量,或使其成为表达式类型变量(例如, Expression<Func<...>>
)。 The latter will make sure that the code is not executed, but treated as an expression which the mock framework can reason about ('is Update
being called with Zombies[0].ConnectionId == null
?'). 后者将确保代码不被执行,但被视为模拟框架可以推理的表达式('是使用
Zombies[0].ConnectionId == null
?来调用Update
)。
It depends how the ControllUser
instance is instantiated. 这取决于
ControllUser
实例的实例化方式。 If the instance that you refer to within the mock is not the actual instance referred to in the code under test, the Setup
will fail. 如果您在模拟中引用的实例不是测试代码中引用的实际实例,则
Setup
将失败。 You will need to ensure that the instance of ControllUser
referred to in the code under test is the same object as the one in the test code. 您需要确保测试代码中引用的
ControllUser
实例与测试代码中的对象相同 。 If it isn't, you'll have to test for it using It.IsAny<ControllUser>()
and a callback, as your first example shows. 如果不是,您将必须使用
It.IsAny<ControllUser>()
和回调测试它,如您的第一个示例所示。 It's hard to say with certainty without seeing more of the code that you're testing. 如果没有看到您正在测试的更多代码,很难肯定地说。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.