Better assertions when verifying Moq’d methods have been called

Alex Brown
ASOS Tech Blog
Published in
2 min readDec 15, 2018
Photo by RyanMcGuire, Pixabay

Moq, according to its GitHub page, is ‘the most popular and friendly mocking framework for .NET’. Mocking frameworks allow you to create a ‘fake’ version of a dependency (typically an interface or abstract class). With this fake, you can then instruct the methods to return values, or invoke behaviour.
Alternatively, you can assert the methods were called, with a certain set of parameters. How we verify these methods were called can affect the maintainability of our tests.

Let’s suppose we have an interface called ICustomerService, which is a dependency of a CustomerController that we are writing unit tests for.

Our method takes a firstName and lastName and creates a Customer object using those parameters.
It then passes that Customer object to the Save method on the injected ICustomerService.
For the purposes of our test, we inject a mocked ICustomerService.
The Save method returns an int, so we set our mocked method to return 1, when it is called with any Customer object.

Our unit test could look something like this:

This test will of course pass. But, if we make a small change in our CustomerController

Now our test will correctly fail. However the exact reason for the failure isn’t clear:

Moq.MockException :
Expected invocation on the mock at least once, but was never performed:
x => x.Save(It.Is(c => c.FirstName == ‘Alex’ && c.LastName == ‘Brown’))

All this tells us is that we didn’t call our dependency with an object that matches. It doesn’t give any indication as to why that object didn’t match.

Moq has a Callback function, which we can use to assign our mocked ICustomerService.Save method to a variable outside of our setup.
Later on, we can use this variable for assertions.

And now, we can individually assert on each parameter:

If we run this test (without fixing our code from the previous failure), it now gives a much clearer failure:

Expected string length 5 but was 4. Strings differ at index 0.
Expected: ‘Brown’
But was: ‘Alex’
— — — — — -^

In summary

  • Avoid using `.Verify(x=> //etc…` for complex assertions. Moq won’t tell you which property didn’t match.
  • Set up a `Callback` instead — and return the arguments with which the method was called, to the caller (our test method).
  • Assert on individual properties of returned arguments.

My name is Alex Brown. I’ve been a consultant Software Engineer at ASOS.com for 18 months. I love writing well-thought out code that does what it’s supposed to do.

When I’m not gazing into my laptop, I enjoy throwing a few weights around in the gym and reading motivational books — most recently Miracle Morning.

--

--