I’ve recently been trying out the Typemock Isolator framework and thought I’d share my findings on it in a set of posts.
Typemock Isolator (TI) is a mocking framework that you can use to help unit test your production code, just like the other popular mocking frameworks out there such as Rhino Mocks and Moq. However, unlike those two, the big selling point of TI is that it allows mocking of concrete, non-virtual method calls, statics, and even calls on “live” objects that it has not had a chance to fake. Of course, all of this power comes at a price – TI is a commercial mocking framework, not open source.
I want to give some simple examples of how the Typemock API looks like at a usage level, then follow up with some comparisons of Rhino, Moq and Typemock (apologies to other mocking vendors – RM and Moq are the two other most popular frameworks out there and the only ones I’ve real experience with), and finally discuss the pros and cons of using a framework such as TI.
Unlike the other frameworks out there, TI requires an actual install into VS in addition to adding TI libraries to your test project (I actually struggled to find out which assemblies were required– It’s the Typemock and Typemock.ArrangeActAssert ones that are needed).
The most recent version of TI has a fairly simple API with a relatively small number of entry methods. Most of these map onto Moq or Rhino methods quite well, so the principles are similar and migration across frameworks should not be difficult. Indeed, I was able to get up and running with a minimum of back-and-forth on the Typemock website.
Like Moq and RM, TI makes heavy use of lambdas, which is no bad thing. Unlike Rhino, which makes heavy use of extension methods, the TI API all sits off its own classes. In some ways this is nice, as you can always see when you’re tapping into the faking framework as opposed to making proper called on your classes, and the API seems somehow cleaner. On the other hand, it can be (slightly) more verbose and not quite as fluent.
The first set of scenarios I want to cover are the basic “catch-all” scenarios that every mocking framework should be able to handle easily.
Creating a mock
Creating a fake object is easy, if a tad verbose:
Personally, I would quickly get bored of typing Isolate.Fake.Instance all the time and would either make a code snippet or more likely make a wrapper method in a base unit test class called CreateFake<T> or something.
You can, of course, fake both interfaces and concretes. When mocking concretes, the returned fake looks to all intents and purposes to be the “real” type – even calls to GetType() say this. However, when you run the code, any of your fake behaviours will magically get run instead of the real methods, whilst other calls you have not explicitly faked do nothing – spooky.
When creating the fake you can also specify its behaviour e.g. whether to act as a “strict” fake (the default is non-strict) and how to act when calling methods that have not been specifically mocked.
Setting fake behaviours
A nice touch with TI is that the default behaviour on methods calls is to always return a fake for reference types, so you don’t need to explicitly create a fake just to avoid null reference exceptions in your code. Indeed, this will chain recursively and also works when your methods return generic collections as well as single objects – very nice.
When you inevitably need to fake a return value on a method or property, you do it as follows:
Essentially, whenever the LoadEmployees() method on our fake is called, you can choose to e.g. Return something, Throw an exception, execute some other code etc.. This approach is pretty much the same for both properties and methods (for private setters you use WillReturn; public ones can be set with regular assignment).
Also notice the WithExactArguments method – the default behaviour for TI is to ignore any arguments when matching calls to mock. So if your method on your fake had five arguments, you don’t have to specify “ignore arguments” as you do with Rhino. This is probably the right thing to do because in your unit tests, most of your faked results will be ones where you aren’t testing the input arguments (at least, in my experience that’s the case).
The other side of the unit testing coin is testing whether a method was called with particular values. This is pretty easy to accomplish, too:
You can also, of course, verify a method was called with the exact arguments specified, or with a subset of arguments – essentially you provide a predicate method which takes in an array of objects which represent the arguments and return a bool stating whether the arguments match or not. This seems a very flexible approach, although I don’t think that it’s quite as elegant as Moq’s approach of It.IsAny<string>() etc. – instead you need to cast the argument to the type and then do your tests. Then again, you can just as easily test if an object is a string with the “is” keyword…
On a side note, because of the Action-style method of verification, testing out and ref parameters is very easy. Surprisingly though I could not find any way to test the number of times a faked method was called, which I have used at least enough to have thought to look for it within Isolator.
As a “standard” unit testing framework, Typemock seems to be pretty decent – the API is easy enough to get to grips with, although it is somewhat different to the Moq and Rhino approaches of a FakeObject composition object (Moq) or extension methods (Rhino) – I’m not suggesting that either of them are necessarily better than Isolator, just that it’s different. The main principles are the same, and the API is neat and tidy (certainly much more so than Rhino’s bloated API) and despite a couple of omissions it works fine.
In the second part of my review, I want to discuss the more powerful, “non-standard” features that Typemock brings, and discuss the impacts of them to your coding designs.