Moq It.Is 不匹配
这段代码:
hub.MockedUserRepository.Setup(r => r.Update(It.IsAny())) .Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null))) .Verifiable();
会打印
NULL = True
所以我在想使用这种匹配会抓住它:
var zombieDisconnectParameterMatcher = It.Is(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(Expression> match) { return Match .Create( value => match.Compile().Invoke(value), () => It.Is (match)); } public static T Match.Create(Predicate condition, Expression> renderExpression) { // ... return default(T); }
如果要执行以下行:
var zombieDisconnectParameterMatcher = It.Is(x => x.Zombies[0].ConnectionId == null);
然后It.Is
将尝试调用名为Match.Create
,该方法返回默认的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
方法时,不会触发回调。 它根本不符合标准,因为它不是空的。 您也会看到validation失败。
要解决此问题,可以内联zombieDisconnectParameterMatcher
变量,或使其成为表达式类型变量(例如, Expression
)。 后者将确保代码不被执行,但被视为模拟框架可以推理的表达式(’是使用Zombies[0].ConnectionId == null
?来调用Update
)。
这取决于ControllUser
实例的实例化方式。 如果您在模拟中引用的实例不是测试代码中引用的实际实例,则Setup
将失败。 您需要确保测试代码中引用的ControllUser
实例与测试代码中的对象相同 。 如果不是,则必须使用It.IsAny
和回调进行测试,如第一个示例所示。 如果没有看到您正在测试的更多代码,很难肯定地说。