Moq It.Is<>不匹配

时间:2013-03-12 21:12:53

标签: c# unit-testing mocking moq

此代码:

hub.MockedUserRepository.Setup(r => r.Update(It.IsAny<ControllUser>()))
                        .Callback((ControllUser usr) => Console.WriteLine("NULL = " + (usr.Zombies[0].ConnectionId == null)))
                        .Verifiable();

将打印

  

NULL = True

所以我想使用这种匹配会抓住它:

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

但事实并非如此。

为什么?

2 个答案:

答案 0 :(得分:9)

通过查看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<...>>)。后者将确保代码不被执行,但被视为模拟框架可以推理的表达式('UpdateZombies[0].ConnectionId == null调用?')。

答案 1 :(得分:1)

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