Thursday, January 08, 2009

.NET Base Class Library types not friendly to mocking with MoQ

I spent some quality time this week driving a design implemented in .NET using unit tests.  It was an enlightening experience and gave me a good glimpse at the quality of the BCL design.  I'm not impressed. We had issues trying to mock System.Net.WebRequest and System.Net.WebResponse and its decendents.  It seems that Microsoft prefers to expose abstract base classes, instead of using interfaces for this.  The aforementioned types are not interface types; they're abstract classes.  We've been using MoQ, a fine mocking framework, at the client I've been working at and I tried to create mock implementations of the System.Net.WebRequest and System.Net.WebResponse types.  No go--these types do not have public constructors.  The non-virtual, non-abstract methods also give MoQ headaches (good write up here about why methods of these abstract class types have to be explicitly decorated with virtual if you want to mock them).  Personally, I'm more fond of exposing interface types, thus alleviating the problem all together.  Very frustrating.  We did continue to unit test and utilized mocks for this, but it forced us to wrap these BCL types with our own types where we could control the virtual decoration.  Yuck!!

4 comments:

  1. Next time I'd suggest you take a look at Typemock Isolator. Same base feature set as Moq, but also able to create fakes of any type, or static methods (even private ctors)

    http://blog.typemock.com/2008/07/is-visibility-of-tested-methods.html

    Roy

    ReplyDelete
  2. Roy, thanks for the tip. Another .NET group at the client that I am consulting with investigated Typemock Isolator and liked it; I believe they are still using it. Is the commercial licensing per developer seat? We don't have a lot of .NET code for this project that I'm currently on, but I'll certainly keep Typemock Isolator in mind when the need arises on other consulting projects. I guess that thing that amazed me, coming from the Java world, is the lack of interface usage in public APIs. Maybe it's just these abstractions.

    ReplyDelete
  3. yes. it is per seat.
    it all depends on what you save vs. what you spend.

    ReplyDelete
  4. Can you recommend any techniques for when you're testing a third-party webservice and can't necessarily wrap the BCL classes? I want to be able test what happens when an exception is thrown by the webservice, but I can't set the appropriate properties on WebException, because I can't do anything with the Response property. I too am using Moq, and not likely to switch to Typemock Isolator in the near future.

    ReplyDelete