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 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 this interface.
Which is a dependency of the class we’re testing:
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" -----------^