Combining Moq callbacks with NUnit
5/05/2010
I didn't want to write too much articles about unit testing, I meant something more development-related thing.
Few months ago two new experienced members joined the team, they shook up the group immediately. Everybody disliked the mocking framework we used that time, so they proposed to use a new one. Now we write the new tests with Moq, the old tests are still using NMock2.
This short post is intended to show two different ways to check the behavior of one method with Moq.
The example will be very simple. Imagine that you have no return value, which you can use for expectation, so you want to verify if your tested method calls your mocked dependency with the expected parameters.
I will use the draft code below in the examples.
As you can see we have the layers here, the BusinessLayer is calling the DataLayer (I omitted the concrete implementation ) after initializing an instance of the Account class.
If the signature of your tested method contains only primitive types your job is very straightforward:
But if you want to pass a more complitaced object instead of primitives, probably you want to verify only some properties, not whole object.
In the first implementation of the test we expect that the SaveAccount method of the DataLayer is called with an instance of the Account class. In the same line there is the second lambda expression, which verifies that the instance of Account class has the expected property values.
This one is fine and works... but only if the SUT (SaveAccount method) will be called every time with the correct parameter. If the test fails, it fails a very bad way:
"Test method TestProject1.BusinessLayerTest.CreateAccount_WithPrivateAccount_VerifyCreatesPrivateAccount threw exception: Moq.MockException: IDataLayer.SaveAccount(MoqCallback.Account) invocation failed with mock behavior Strict.
All invocations on the mock must have a corresponding setup."
This is a typical situation when TDD yields profit for us. The failing test shows that we have some functionaly covered with a testcase and after an inaccurate modification the our new test will help us to find the bug.
But does the error message above really help us to find the problem? If this error is displayed to somebody else, he/she would say "WTF?". Of course this means he/she will have to put a breakpoint in the test and check what's going on. Troubleshooting is less time consuming if the method name and error message of the test are descriptive. In our case the method name is OK (we understand what the method should test), but it's hard to spell out what is wrong: the test code or the SUT.
To generate useful error description, you can combine Moq callbacks and NUnit (or your favourite framework) assertion API. According to the documentation the definition of the mock callback is the following: "Specifies a callback to invoke when the method is called that receives the original arguments."
We need exacly this, the original arguments of the called method. Most of the tutorials are writing this argument to the console....what a waste!
Let's change the Setup of the mock to verify only the type of the passed parameter and define a Callback which checks the expected property with your assertion API.
In this example we verified only one property, I recommend to extract the multiple assertions to a new method and call it from the Callback.
This is not rocket science. You can find the Callback feature of the mocks in the Moq QuickStart or with Visual Studio IntelliSense. I checked few basic Moq tutorials, but I haven't found this practice there.
Ohh, I almost forgot the main point...the error message of the failing test:
Assert.AreEqual failed. Expected:<Private>. Actual:<Enterprise>.
This is generated by Visual Studio assertion API, but the NUnit one will look something similar.
Read full article: Combining Moq callbacks with NUnit


1 comments:
Post a Comment