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
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. 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
?').
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With