简体   繁体   English

Moq It.Is <>不匹配

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM