Touching a hot iron: Typemock Isolator

January 11, 2009 21:29

Typemock Isolator costs €449.

Good news: there is a Community Edition that is free[1].When you download the Isolator you get the full Enterprise Edition andafter 21 day the  evaluation licence expires and you're left with thefree features only.

And other mocking frameworks just wither away if you compare the feature sets. (Disclaimer: I'm using Typemock at work.)

Here goes the test for our touch-and-yell scenario[2].

[Test, Isolated]
public void TouchHotIron_Yell()
{
    var hand = Isolate.Fake.Instance<IHand>();
    var mouth = Isolate.Fake.Instance<IMouth>();
    Isolate.WhenCalled(() => hand.TouchIron(null)).WillThrow(new BurnException());
    
    var brain = new Brain(hand, mouth);
    brain.TouchIron(new Iron {IsHot = true});
 
    Isolate.Verify.WasCalledWithAnyArguments(() => mouth.Yell());
}

 
Just a few words about the sample. The history of Typemock is quite long, and severalsyntaxes are supported by now. The one displayed above is called AAA(Arrange, Act, Assert). It appeared in mid-2008,along with lambda expressions support.  Here, Isolate is the only API root, with just four properties and two methods on it. Isolated attribute is used to clean up the expectations when the test is finished.

The two remaning syntaxes are Reflective Mocks and
Natural Mocks. The former uses string based method names, the latter is type safe and therefore a more preferred wayof mocking even though it explicitly uses the Record/Replay. And, as we know, Record/Replay has been heavily criticized for its unnatural style and sometimes even considered as an example of exposing internal implementation of a framework for no reason.

What others can't do.

But let's look at a different scenario: imagine that the only constructor the Brain class has is a parameterless one that creates _hand and _mouth internally. Here's the test:

[Test, Isolated]
public void TouchHotIron_Yell()
{
    var hand = Isolate.Fake.Instance<Hand>();
    var mouth = Isolate.Fake.Instance<Mouth>();
    Isolate.Swap.NextInstance<Hand>().With(hand);
    Isolate.Swap.NextInstance<Mouth>().With(mouth);
    Isolate.WhenCalled(() => hand.TouchIron(null)).WillThrow(new BurnException());
   
    var brain = new Brain();
    brain.TouchIron(new Iron { IsHot = true });
 
    Isolate.Verify.WasCalledWithAnyArguments(() => mouth.Yell());
}


With that
Swap call, we tell the Isolator that the next object of the given type should be swapped with the mocked one. So, hand and mouth that get created inside the Brain constructor, get mocked.

No other mocking framework can do that. Instead, we hear that calling
new inside a constructor is a bad practice, and we should be just passing everything in (that's called a Dependency Injection pattern).

And it's pretty damn true. In most cases.

Pendency injection.

However, consider this. Dependency Injection is the only way to isolate a piece of code, and probably it's being  overused. It has become a silver bullet in the mocking world, that is somewhat dangerous. Doesn't it remind you the situation with Singleton? There are some cases where it should be used, but since it's a relatively easy pattern to understand, people often start writing singletons until they mushroom out of control. It's quite easy to find some code with singletons in places where they don't fit well.

Could it happen to Dependency Injection? Aren't we adding more classes/interfaces just for the sake of testability, at the same time excessively increasing the complexity of our systems, the time to be spent in development and maintenance? 

Pros and cons.

The goal of Typemock Isolator is pretty clear: do not force you to design things in a particular way, and allow testing as much as you can with the existing design. It's a great fit for legacy apps and apps you can't control.

Such applications can heavily use static types or methods and create objects inside constructors. While testing them you might need to mock sealed or private classes
something that only Typemock can help you with. On the other hand, for the green field projects you probably can safely go with NMock2 or Rhino Mocks or Moq: no charge and available source code is something that could really tip the scale. Or you may consider a free edition of the Isolator.

But of course even Typemock has its weaknesses.

It has problems with mocking fields (you can always turn a field into a property but it's a different story). [Update: you can mock fields in Reflective and Natural Mocks]. Next, as soon as
Typemock assemblies use types from mscorlib, it cannot mock these types DateTime.Now and so on... [Update: now it can mock DateTime.Now and File.ReadToEnd] It might be seen as a minor imperfection, but if the guys emphasize thattheir framework does not require you updating the existing design,mocking fields or mscorlib types is as important as, say, mocking static methods.

Sum up.

Pros:
1. Extremely powerful. Can mock static methods, sealed and private classes, does not need Dependency Injection to work.
2. Type safe.
3. Simple API.

Cons:
1. Not open source and no free Community Edition.
2. Cannot mock fields.
3. Cannot mock
mscorlib types.




Footnotes.

[1] There are three editions. Community Edition is the basicone (and free), with Professional one you'd get code coverage, NaturalMocks and support for mocking events. In Enterprise Edition, you getall that plus conditional expectations, advanced arguments switchingand a lot of other highly advanced features. Here you can read more about the differences (unfortunately, ther's no direct link to this extremelly important page from "Download" or "Buy now" section or elsewhere on the surface of typemock.com).   

[2] If you happen to come across this post before reading the original story of touching a hot iron, you may want to read it over. And here is the code for the types used in the example.

 


Comments

Comments are closed