views:

1685

answers:

4

I am just starting to do Test Driven Development, and I am wondering the major differences between RhinoMock, TypeMock, and NUnit's built-in mocking?

Any information would be greatly appreciated!

+13  A: 

TypeMock is a commercial product (meaning you'll have to pay for it) but will allow you to mock concrete objects - unlike RhinoMocks/NUnit/MoQ which can only mock an interface/abstract class. How it achieves this is borderline black magic, but it does some very clever things with the CLR.

This can be particularly useful when you use libraries in your project that don't use many interfaces. So you could, for example, use TypeMock to mock out a LINQtoSQL datacontext, or Sharepoint objects. However, if you are using TypeMock this is no excuse for bad design in your application.

As far as I'm aware, aside from minor syntax differences, most of the mocking frameworks have moved away from the old record/playback model. Commonly, you set up your mocks by writing expectations using a Fluent Interface.

Personally, I have only used MoQ and I <3 it.

Kirschstein
Static and sealed classes are not always a bad design, but it is impossible to mock them using RhinoMocks/NUnit/MoQ. Do you just abandon the whole feature set, just because your tools don't support it?
HeavyWave
@HeavyWave they're not _always_ bad design, but if you find yourself in a situation where you want/need to mock them out, then it probably is bad design _this time_
Kirschstein
+5  A: 

A video called TDD - Understanding Mock Objects by Roy Osherove is very helpful in learning the differences of the different mocking libraries. He doesn't go in great detail of every aspect, but enough for you to understand. I hope this helps. Roy is also the Chief Architect for TypeMock and is a very influential figure in the unit testing arena. I couldn't recommend this video enough for someone who wants to learn how to use mocking and also learn about the library's available.

The main difference between TypeMock and the open-source library's is that TypeMock uses the Profiler API provided by Microsoft instead of a dynamic proxy. This allows TypeMock to mock concrete classes and static methods. In case you aren't sure what the profiler is, it is the same API that is used by tools like JetBrain's dotTrace and RedGate's Ants .Net profilers. TypeMock just uses the API in a different way to fake(mock) what you tell it to.

@RichardOD, thanks for the reminder, his book "The Art of Unit Testing" goes into greater detail where the video doesn't. I own the book and it is very informative.

Dale Ragan
He also has a great book too.
RichardOD
+2  A: 

Hi there.

I use TypeMock all the time and have found it to be a very powerful tool that can improve the coverage of my unit tests. This is because I work with SharePoint and only TypeMock can allow me to mock out SharePoint classes - since they are concrete classes and not interfaces.

Mocking SharePoint classes is not possible with RhinoMock, Moq, NUNit, etc since (I believe) they require interfaces to mock objects, rather then being able to mock the actual concrete classes.

If your code does use a lot of interfaces, and you don't require mocking concrete classes then TypeMock is a bit pricey, but for the power you get, it's worth it.

Cheers. Jas.

Jason Evans
You could always just wrap the SharePoint classes in your own simple wrapper class which just forwards the calls. The wrapper class can then be accessed through an interface and can be mocked. The wrapper class could also act as a facade to simplify your interaction with the 3rdparty classes. You don't need TypeMock here.
Wim Coenen
+5  A: 
  • Rhino.Mocks is an open source, continuously developed and improving framework by one of the industry's most prolific developers. It has been around for a while and hence supports quite a few different paradigms for mocking. It can be a little tougher to learn therefore in the sense that you might find tutorials for the "old" way of doing things. Here's a tip, SetUpResultFor() and Expect.Call() are the old ways of doing things. The new way is mockObject.AssertWasCalled().

I have not had any personal experience with these others but...

  • MOQ is an open source, continuously developed and improving framework by one of the industry's somewhat less prolific developers (as compared to Ayende). It is newer and therefore lacks some features that Rhino.Mocks has. This is usually not a problem since these features tend to be ones that are somewhat deprecated in Rhino. I have heard that because of this it is slightly easier to learn (mocking frameworks aren't hard to learn by the way).
  • NUnit Mocks is very quaint as far as mocking goes. It doesn't support the currently preferred Arrange-Act-Assert syntax relying instead on Expect-Verify (record/replay). It also relies on strings to identify method and property names instead of lambdas. This makes it significantly resistant to refactoring. This is a serious problem. I would not recommend it.
  • TypeMock Isolater is a hardcore for-pay mocking framework from a company (owned by?) Roy Osherove - a guy who knows his testing but also has some mildly controversial opinions as to how to apply it. It is really intense as far as what it can do - getting down to the low level and modifying how CLR objects work. The philosophy behind TypeMock isn't really 100% TDD however. Part of the benefits of TDD is that by embracing the limitations of Mocking frameworks you will design better code. TypeMock blasts those limitations to pieces. As far as I know it is mostly used by people who are trying to get code they have no control over under test.
George Mauer
Downvote? Was I wrong about something?
George Mauer
The downvote wasn't from me, but I do disagree that "embracing the limitations of Mocking frameworks you will design better code".I mean, are you serious? Say I want to follow the "information hiding" principle and fully encapsulate a non-public helper class. Those limited mocking tools wouldn't allow me to! How does exposing that helper class and reducing encapsulation would lead to better code?
Rogerio
@Rogerio - Thats exactly what I mean. If you need to mock something you're creating in your object then you are either testing at too fine-grained a level (ie, if its a helper class test with it in place) or you should be injecting it as a dependency. The limitations of Rhino Mocks and MoQ force you to use Dependency Injection which is a basic tenet of good OO design. They also cannot mock statics/global states - these also are discouraged in a properly architected design. And if you are using such techniques they should be transparent to your client (test/mocking) code.
George Mauer
Yes, I thought that as well: not mocking the helper would be fine in many cases. But this isn't the point. The problem is not having that option. Real-world situations may exist where I would want to mock it, and I should be able to do it without changing production code first.And DI is definitely no "basic tenet of good OO design"! It's just a way to provide a client object with references to needed external dependencies, nothing more. If you think otherwise, show me the evidence.Static methods have their place as well, otherwise modern OO languages would not allow them.
Rogerio
I am not saying the a juggernaut like TypeMock does not have its place. I am saying that if you have full control over your code and follow good practices you will not need any of the advanced Mocking features. Evidence? Among the Jermey Miller, Rob Connery, Scott Bellware, etc crowd of powerhouse devs I have yet to hear of them using anything but Rhino and MoQ. And Ayende is a smart guy (possibly the smartest) - if he felt he needed to mock statics he would have done it. As for DI being a primary tenet - it's the freaking D in SOLID!
George Mauer
No, the "D" in SOLID stands for "Dependency Inversion Principle", and is something completely different from Dependency Injection. But don't take my word for it, read about it.Besides, several of those supposed SOLID principles of OO design are pretty lame. And yes, I can explain why. Don't believe everything the so-called gurus preach. Try reading the source code for FitNesse (from the same author of "Clean Code" and SOLID) and tell me if that is really good OO code.
Rogerio
The real reason tools like Rhino, Moq, etc. don't support mocking of static methods, non-virtual methods, constructors, and so on is simply because this stuff is not as simple to implement in the tool. If it was easy, I am pretty sure those tools would provide it.
Rogerio
Also, Rhino Mocks went through several different APIs in its short development history; for example, the latest API that supports the "AAA" (Arrange, Act, Assert) syntax was a reaction to Moq. So, I wouldn't be so sure about how smart these guys really are...
Rogerio
Regarding the D in SOLID - you're technically correct but I disagree that they're completely different. Dependency Inversion is a more general term but constructor injection is overwhelmingly the preferred method. Regarding good OO and SOLID - I will assume you agree that SRP and Open/Closed are good - how many ways do you know of achieving these without good dependency injection? (The only other 2 I know are static locators or use a dynamic language). Finally, I don't agree with Ayende on everything, but for the things we disagree on chances are he's right. Hes an authority for good reason.
George Mauer
DIP is about the reuse of a high-level module, which is supposed to be achieved by "inverting" its dependency on low-level modules. DI is about externally configuring those dependencies, and does not require the inversion.I am in favor of high cohesion, but I dislike the SRP formulation (too vague and imprecise to be useful).OCP makes no sense because code is supposed to be changed (its "soft" after all); it goes against the idea of refactoring, and contradicts the whole point of automated testing; it's a 20th century anachronism.What exactly makes Ayende an authority?
Rogerio
Rogerio, read Wikipedia's or PPR's article on DIP - they clearly describe it and say that Dependency Injection, Service Locator, and Plugin are some of the patterns used to achieve it. I think you might be thinking of the wrong thing! Wikipedia also mentions Uncle Bob not only as a proponent of it but as the originator of the term.He says its mandatory for good OO. As for what makes Ayende an authority? Well he is widely respected by nearly everyone, gives fascinating talks, hobnobs with the likes of Fowler, Evans, and Feathers and writes spectacular working software! What else would you want?
George Mauer
By the way, I'm not claiming that Ayende is any more an authority than Roy Osherove. I'm also not saying that we should follow them or anyone blindly. I'm saying that lots of highly respected working developers manage to produce spectacular results staying only within the limitations of Rhino Mocks. They do not do this by ignoring the any test where they need to mock DataRow and they do not do it out of some fealty to a tool or tool author. They do it because these tools ALREADY HAVE all the features that they need!
George Mauer
I read all those articles, and I do understand them. You are correct about DI, Service Locator, and Plugin being used for DIP; I never said otherwise. But the concepts ARE different, as I explained before. Bob Martin originated DIP, but NOT DI, which was coined by Martin Fowler in http://martinfowler.com/articles/injection.html.Martin is wrong about DIP's importance to OO. This is not just my opinion, as evidenced by the lack of references to DIP in other well known books and articles about OO from authors such as Fowler, Josh Bloch, GoF, Andrew Hunt, Steve McConnel, Brian Kernighan, etc.
Rogerio
No problem about Ayende, I was just curious. I am glad to see that you don't just follow others blindly. But you should be more open-minded about the consequences of those limitations in the mocking tools.When a developer creates a separate interface or declares methods virtual just for the sake of unit testing, he is doing a disservice to the project, by adding unnecessary, pointless complexity. A good mocking tool should never force that. Trying to "force" developers into good OO simply doesn't work, because the bad ones will always circumvent it.
Rogerio
One concrete example that hopefully will get you thinking: the official DDD sample application (from Eric Evans).Consider the se.citerus.dddsample.application.BookingService interface. It has a single implementation class in the "impl" subpackage, named "BookingServiceImpl". There is a unit test class for this, "BookingServiceTest", which uses EasyMock, a very limited mocking tool for Java.Now ask yourself: what is the point of this interface/implementation separation? The "booking service" belongs to a single use case, and is clearly too application-specific to be reusable.
Rogerio
Wow, lots to reply to. First of GoF and many/most of the patterns described in patterns books use dependency injection. Second, no one is trying to force anything - I am glad TypeMock exists but the others are also sufficient. Third - can't guide developers to good design? You must've never used WebForms cause guiding them to bad design has been quite easy.
George Mauer
Finally, there are many uses for interfaces other than to allow mocking and alternate implementations; decorator, composite, CoR. Interestingly most of the ones I can think of have to do with SRP and O/CP so maybe our basic disagreement about the importance of these two to good software design is the problem. Perhaps you should start a new question for how important is Open-Closed Principle really? We could continue this there.
George Mauer
OK, I will think of the question. But my original intent was not to discuss what OO is, or which principles are good or not. The central question here is the validity of using limitations in a mocking tool as a "guide" to design. My opinion on this is that good designs are more likely if you don't have to worry about those limitations.
Rogerio
The question about OCP was created: http://stackoverflow.com/questions/1416476/is-the-open-closed-principle-a-good-idea
Rogerio
Wow, an internet argument that's ending in a civil manner? Check the skies! Is it the end of days? I'll follow up on the other thread but a quick question since I'm curious. The process of TDD also imposes certain limitations on development. I would assert that these limitations are one of the things about TDD that help one learn how to create good designs. Do you agree? If so then you agree that limitations can help one learn - do you just think the limitations applied by Rhino Mocks are the wrong ones?
George Mauer