A Red Herring When Using Moq to Mock Methods With Optional Parameters

I recently spent some time writing unit tests for some code that required me to mock an object that has a method with optional properties. I used the Moq framework, and when I set up the method in question, I defaulted the optional parameters. This was required, as leaving them out of the Setup() call was not allowed.

Also as part of my set up of this method, I instructed Moq to return the first parameter as the return value. I've had plenty of experience with Moq and setting up return values for mocked methods, but it didn't prepare me for the mistake I had unknowingly made. Here's how I set the method up originally:

_repoMock.Setup(x => 
   x.Save(It.IsAny<Click>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<bool>()))
    .Returns((Click click) => click);

When I ran my unit test, the method above resulted in a "Parameter count mismatch" exception. I checked and double-checked my arguments, and went about trying to resolve the issue, until I finally realized my problem: it wasn't the arguments in the method signature set up that it was complaining about, it was the parameters specified in the Returns() call where I was specifying the return value. It was a very stupid mistake and I could smack myself for making it. Seriously. What was I thinking???

Here's the corrected version of the method set up -- note that all of the parameters are represented in the Returns() call, even the ones I'm not interested in:

_repoMock.Setup(x => 
   x.Save(It.IsAny<Click>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<bool>()))
    .Returns((Click click, string username, bool flush, bool addToSet) => click);

When I saw the exception "Parameter count mismatch" occurring when trying to call the mocked method, I assumed it meant the parameters being passed to the method. Nope. It meant the parameters I had referenced when setting up the return value. I'd done this many times before, but for whatever reason had a mental lapse this time and only thought to specify the one in my Returns() call.


Jim said…
Thanks for this, after an hour of frustration I found this and now I can get to bed before midnight!

Popular posts from this blog

A Generic Method Using HttpClient to Make a Synchronous Get Request

The Cause and Solution for the "System.Runtime.Serialization.InvalidDataContractException: Type 'System.Threading.Tasks.Task`1[YourTypeHere]' cannot be serialized." Exception

How To Mock Out Child Components In Unit Tests of Angular 2 Code