It seems that for some reason, Microsoft has created an interface for it's messenger and then gone and implemented the logic as extension methods on the interface itself.
Unfortunately, I cannot use this beautiful solution: http://agooddayforscience.blogspot.com/2017/08/mocking-extension-methods.html - because IMessenger extensions calls implemented code on Messenger with an internal type as argument.
Why would Microsoft go to such lengths to make unit testing hard? (If you know a good, technical reason for this, please comment with the answer. I am very curious).
I want to unit test the ViewModels, which injects IMessenger. So how do I do this?
My solution is: Wrap IMessenger in a wrapper with an interface and inject that instead.
Is there a simpler/better solution? (I want it to be easy to understand and maintain).
Moq is incredibly extensible, and provides an extension point for exactly this purpose. You can provide custom type matching logic by creating a type that implements ITypeMatcher. To match the IMessenger.Send
signature, for instance:
[TypeMatcher]
public sealed class IsAnyToken : ITypeMatcher, IEquatable<IsAnyToken>
{
public bool Matches(Type typeArgument) => true;
public bool Equals(IsAnyToken? other) => throw new NotImplementedException();
}
You can use this to write Setup and Verify code exactly like It.IsAnyType:
mockMessenger.Setup(x => x.Send(It.IsAny<MyMessage>(), It.IsAny<IsAnyToken>());
...
mockMessenger.Verify(x => x.Send(It.IsAny<MyMessage>(), It.IsAny<IsAnyToken>(), Times.Once);