Introduction
As I mentioned in the last post, that I have been working on Agile methodologies for more than 18 months now. During this time I been involved in project development using TDD. As part of writing and executing automated Unit Tests, our team has been using Dynamic Mocking Frameworks like NMock 2 and Rhino Mocks. Here is an attempt to compare different mocking frameworks I have worked with.
Different Dynamic Mocks
In simple terms mock is an object which acts as a proxy for some real world object. Its a dummy object which is used to mimic the real world object. Every time I try to explain some person who is new to TDD the usage of mocks the first question that pops out is why do we need mock objects?
1. One of the basic need for having mock object is to follow the unit testing principle which says that we should be testing the System Under Test (SUT) in isolation. If we follow this principle only the logic related to one class or method should be tested using a unit test and we shouldn't be really worried about the dependencies of that class which we are testing. All the dependencies should be tested separately. In order to manage the dependencies we use mock objects. We can replace the dependencies with fake objects or mocks.
2. Another reason why we use mock objects is to improve the performance of executing the unit tests. If we were to construct the real objects or dependencies it might be time consuming.
3. This also helps us in removing dependencies like external web services or the physical database server. We can mimic these behaviours using a mock object as long as the mocks use the same interface.
4. Another alternative to using the dynamic mock object is to create a fake object which are also called as static mocks. But the problem I see with this approach is that every time there is a change to the service contract or the interface which the mock implements, the hard coded mock need to be updated as well. This results in maintenance problem.
Initially my team was using NMock 2 for mocking. It has got some nice features like it provides a very fluent interface for setting expectations as well as for different types of matchers. The problem I feel with NMock 2 is that it uses magic strings for the names of methods and properties. This does not provide much type safety. In terms of Rhino Mocks matchers are referred as argument constraints.
Type safety is the biggest advantage Rhino Mocks has over NMock 2. Apart from type safety Rhino Mocks also has a Record and Playback option. It can also mock concrete as well as abstract classes. Rhino Mocks has 3 types of mocks Strict Mock, Partial Mock and Dynamic Mock. It also has the facility to set expectations in ordered and unordered sequence.
As compared to these two commonly used Dynamic mocking frameworks, Moq is relatively new. It has the distinction of being the only library for .Net which is developed from scratch using the features of C# 3.0 and 3.5 framework. It relies heavily on LINQ and Lambda expressions. So knowledge and experience of these C# features is a must if someone wants to try Moq as the preferred framework.
Instead of creating something from the scratch I decided to use the hypothetical sample which was published on NMock site as a quickstart. You can read more about it from http://www.nmock.org/quickstart.html. I have made minor modifications to the test code to follow the AAA syntax. I have attached the solution code at the end of the article. Instead of going into the details of how to create a mock repository and explain each and every method, I would like to highlight the main differences in the way expectations are set on the mock instance in these 3 frameworks.
NMock2
Expect.Once.On(_mockCurrencyService).
Method("GetConversionRate").
With("GBP", "CAD").
Will(Return.Value(conversionRate));
Rhino Mocks
Expect.Call(_mockCurrencyService.GetConversionRate(britishAccount.Currency, canadianAccount.Currency)).
Return(conversionRate);
Moq
_mockCurrencyService.Setup(
mockCurrencyService =>
mockCurrencyService.GetConversionRate(britishAccount.Currency, canadianAccount.Currency)
).Returns(conversionRate);
As we can see from the above statements, Rhino Mocks and Moq have lot of similarity in the way the expectations are set on the mock currency service. But in case of NMock2 we need to specify explicitly what is the method name, the parameters and also the return type. In one way the syntax is quite intuitive, but lacks type safety. Also I feel that having to type something like
Will(Return.Value(conversionRate))
is bit too much just to set a return value.
Conclusion
In some future post I would like to highlight how to verify constraints and also do argument matching using matchers. But for the time being I feel Rhino Mocks has advantages over NMock 2. I haven't worked much with Moq. So I am really not in a position to comment which one is good among Rhino Mocks and Moq. Both might be used in different contexts. If a completely new development with .Net 3.5 framework is to be started Moq seems to be a good option.
This article wouldn't be complete without mentioning the difference between a mock and a stub. This is well documented by Martin Fowler in his post Mocks Aren't Stubs. At a very high level I would say you would use mocks to test interactions between different layers or classes of your applications. Stubs are used to stub some behaviour. Using a stub will not fail the unit tests. But mocks can cause tests to fail if all the interactions are not performed as per the expectations.
You can download the complete source code from this location. If you are facing some problem downloading the code from the link, you could also try pasting the following URL in your browser
No comments:
Post a Comment