Mocking frameworks comparison

October 4, 2009 22:14

About 9 months ago I posted a comparison of different mocking frameworks. A lot has changed since then - armloads of bugfixes, gratifying influx of new features, and even a new mocking framework (!) - so time is ripe for a new comparison.

But before I move on, here's a very brief list of changes.

Changes since January 2009.

1.
NMock2 caught up with its major rivals, and now supports 

  • nonstrict mocks - it's now perfectly ok to "unexpectedly" call a method on a mock
  • (wow!) mocking classes 
  • partial mocks (that is, mocking only part of a type while leaving some methods unmocked)

2. Isolator made a huge leap forward - now you can

  • mock mscorlib types - yes, mocking DateTime.Now is no longer an issue!
  • completely redefine mocked method with DoInstead
  • test ASP.NET with Ivonna and test SharePoint with um, Isolator for SharePoint
  • easily write tests in VB
3. Rhino Mocks hasn't changed much but
4. Moq hasn't changed much either
  • apart from introducing linq to moq which allows you to set up multiple mocks (with multiple conditions, etc) in one operator
5. And now we have Moles, dark horse of mocking
  • that supports mocking static methods
  • ...and non-virtual methods
  • ...and even members of sealed classes (!!!) 

Current comparison.

The comparison table follows. As all
frameworks now support both strict and non-strict mocks, and can mock both classes and interfaces - I'll omit that from "Pros".

Pros  Cons  Comments 

 
NMock2

Open source and free.

Expressive and easy-to-learn syntax.

Clear internal errors (supports custom messages as well).

Supports partial mocks.

Very fast.

Heavily relies on Dependency Injection pattern.

Type unsafe: expectations are string based.

Cannot mock non-virtual, non-abstract and static methods, cannot mock sealed classes and private interfaces.

Does not support recursive mocks [Update: or maybe it does - see comments].

With extension methods of C#3, one can easily extend NMock2 to be type safe, at least for simple scenarios.

String based expectations is a deliberate choice - the team believes it gives you more power - and to make our lives easier, they made some terrific contribution. They wrote an open source Resharper plugin to help us writing all those strings.

One consequence of using string based expectations is that NMock2 is very fast as it doesn't parse expression trees at runtime.

Rhino Mocks

Open sourse and free.

Type safe.

Advanced features: s
upports recursive mocks and partial mocks. 
Heavily relies on Dependency Injection pattern.

Cannot mock non-virtual, non-abstract and static methods, cannot mock sealed classes and private interfaces.

Poor intellisense experience, all RM methods just appear in any call to any object in a test.
Intellisense is polluted because RM returns the actual <T> from its GenerateMock and other calls, but in order to allow calling Expect, Stub and other methods, RM does so by introducing extension methods on any T.

A lot will be changed with RM 4.0 which will break backwards compatibility and presumably make the API much easier to use.


Moq

Open source and free.

Expressive and easy-to-learn syntax.

Type safe.

Advanced features: supports recursive mocks, partial mocks.
Heavily relies on Dependency Injection pattern.

Cannot mock non-virtual, non-abstract and static methods, cannot mock sealed classes and private interfaces.

Need to use mock.Object property if we pass the mocked interface/class over.

Moq is the youngest framework, bereft of the "legacy" burden of record/replay model. This makes it pretty straightforward and friendly, and a lot of work is being done to support and enhance the clear API.

In order to keep clean intellisense, Moq separates between mocked objects and expectation builder objects - that's why you need this Object property on a mocked instance
.

 
Isolator

Does not rely on Dependency Injection pattern.

Expressive and easy-to-learn syntax.

Type safe.

Advanced features: supports recursive mocks, partial mocks.

Überadvanced features: can mock static methods, sealed and private classes.

Not open source and not free.

Does not support custom error messages in expectations.

Is the slowest mocking framework.
Isolator is the most powerful mocking framework, and sometimes its power is (unfairly?) considered as its main weakness. 

Mocking static methods etc is possible because it uses CLR profiler to intercept the calls. And even though it seemed not possible, Typemock guys went an extra mile and provided support for mocking mscorlib - DateTime.Now and File.ReadAllText(), perhaps more to follow. Awesome.

 
Moles

Free.

Does not rely on Dependency Injection pattern.

Type safe.

Advanced features: supports recursive mocks, partial mocks.

Überadvanced features: can mock static methods, sealed and private classes.


Not open source and still in a very deep beta (current version is 0.16).

Cannot be used without Pex.

A bit cumbersome syntax.

Mocks need to be regenerated each time you change the system under test.
Moles is designed to suppot a "parametrized unit tests generator" called Pex, which purports to change the face of unit testing forever: instead of creating mocks dynamically, Pex generates them at compile time.

One consequence of static generation is that mocks work extremely fast  (however, notice that performance comparison was done for Stubs, not Moles).

As Isolator, Moles uses CLR profiler to intercept method calls - thus being able to mock static methods, etc.


The reason for NMock2, Moq and Rhino Mocks for being unable to mock non-virtual methods lies deep inside the frameworks. They all use Castle Dynamic Proxy to proxy the types they need to mock, and Dynamic Proxy cannot intercept calls to non-virtual, non-abstract methods.

That's that. Happy mocking!

If you want to see all frameworks in action - there's Mocking Frameworks Compare open source project that provides a unified set of tests written against Moq, NMock2, Rhino Mocks, Isolator and Pex Stubs.

(And don't forget to check out Roy Osherove's bi-annual poll on mocking frameworks.)


Comments

Comments are closed