Moq It.Is<> not matching

后端 未结 2 1315
醉酒成梦
醉酒成梦 2020-12-16 05:01

This code:

hub.MockedUserRepository.Setup(r => r.Update(It.IsAny()))
                        .Callback((ControllUser usr) => Consol         


        
相关标签:
2条回答
  • 2020-12-16 05:12

    By looking at the source code of It, it has to do with expression trees. 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. I assume ControllUser is a class and therefore zombieDisconnectParameterMatcher will be 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. 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<...>>). 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?').

    0 讨论(0)
  • 2020-12-16 05:29

    It depends how the ControllUser instance is instantiated. 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. 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. If it isn't, you'll have to test for it using It.IsAny<ControllUser>() and a callback, as your first example shows. It's hard to say with certainty without seeing more of the code that you're testing.

    0 讨论(0)
提交回复
热议问题