In the previous post I’ve explained (briefly) what are fake objects and why they should be used – if you haven’t read it yet – I suggest you do so now.
In a nutshell fake objects are used to break dependencies in unit tests to make the test faster, predictable and enable you to test the un-testable.
In this post I will show code! in fact we’re going to use isolation (Mocking) frameworks to create our very first fake object. I apologize in advance for using C# for my examples – just keep in mind that the ideas thought in these posts will also work if you use other programming languages and other isolation frameworks.
Let’s pretend that we want to unit the following code:
Note that I call another class in order to access my “database”, UserRepository, and obviously I haven’t got a database just yet – we’ll get to that in a minuet.
Simple – isn’t it? We have a pretended user service that help us manage users in our make belief site. Now let’s say I need to test the AddNewUser method. As you can tell from the code above I want to test two scenarios:
First I’d like to write a test that would verify what I secretly know – that my code works. The test would probably look something along these lines:
The test is simple enough I call the method expecting a specific exception to be thrown. If you are not familiar with the Throws method on lines 15-16 don’t worry – I wrote about it in a previous post.
The good news is that running the test causes an exception to be thrown, the bad news is that it’s a different exception from what I expected – The UserRepository class has not been properly configured (in my case not event implemented). In fact because that class (probably) calls a database I would not want to actually call it in my test. Doing so would require that I create a database and initialize it prior to running my tests and it’s not really what I need to test here.
Ideally I would like to fake the data access layer to return the needed result – in this test I just want it to return true whenever it was asked if a user already exists.
Luckily for us that’s exactly what Isolation (mocking) framework do. In .NET there is an option to use either Moq, RhinoMocks or Isolator, there are other isolation framework out for .NET but these are the top three.
I’m going to show how to create a fake object and set its behavior using Moq and Isolator – I leave it up to you to check and see how RhinoMocks does it.
Moq create a fake object using inheritance, it will subclass the object we want to fake and change the implementation of the methods according to our specifications, so in order for it to work we need Repository.UserExist to be a virtual method.
Note: Moq uses inheritance to create the fake object – so make sure that the method’s you’re faking are virtual and that the faked class is not sealed.
The test code has changed a bit – this is how it looks now:
If you’ve been paying attention you couldn’t have missed that I’ve added a new c’tor to our UserService class. The reason I did this is to enable passing the fake object to the production code. In fact the new c’tor is pretty straight forward – I replace the created repository with this “fake repository”:
This act of making the code easier to fake is referred as “design for testability” or “refactor for testability”.
And so with a new dll and a few minor code changed our test now passes – that it it throws an exception.
Typemock Isolator is a bit different from other isolation frameworks – it doesn’t use inheritance to create fake objects instead it uses the .NET profiler API to intercept low level method calls and replace them with fake code. This enable Isolator to fake about any method there is out there not just virtual methods along with other goodies. The other difference is that it costs money and if you haven’t had a good look at my blog – I work there.
The main benefit of using Isolator you do not need to change your production code in order for it to work:
Just like in Moq we create a fake instance of UserRepository (line 4), set its behavior (line 5) but unlike Moq we can tell Isolator to replace the next instance created of a certain type with our fake object (line 7).
In face using Isolator I do not need the faked object methods to be virtual – it just work.
The result is the same – the test passes.
In the next part I’m going to explain about another important feature of Isolation frameworks – stay tuned…
Labels: .NET, Mock objects, Unit tests