【问题标题】:Moq It.Is<> not matchingMoq It.Is<> 不匹配
【发布时间】:2013-02-28 14:46:00
【问题描述】:

这段代码:

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();

但事实并非如此。

为什么?

【问题讨论】:

    标签: c# unit-testing mocking moq


    【解决方案1】:

    通过查看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&lt;ControllUser&gt;() 将尝试调用一个名为Match.Create&lt;ControllUser&gt;() 的方法,该方法返回默认值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&lt;Func&lt;...&gt;&gt;)。后者将确保代码不被执行,而是被视为模拟框架可以推断的表达式('Update 是否被Zombies[0].ConnectionId == null 调用?')。

    【讨论】:

    • 我向您鞠躬,@Caramiriel 先生。
    【解决方案2】:

    这取决于ControllUser 实例的实例化方式。如果您在模拟中引用的实例不是被测代码中引用的实际实例,Setup 将失败。您需要确保被测代码中引用的ControllUser 实例与测试代码中的对象相同。如果不是,您必须使用It.IsAny&lt;ControllUser&gt;() 和回调对其进行测试,如您的第一个示例所示。如果没有看到更多您正在测试的代码,很难确定地说。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 2014-01-02
      • 2016-09-21
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多