Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Wicked Cool Jobs

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Why and When to Use Mock Objects

In the last post I introduced mock objects and talked about some of the various flavors of fake objects.  In this post I want to talk about when and why you would use a mock object.  The main benefit of using mock objects is increased testability throughout a system.  A secondary benefit of mock objects is an improved ability to do continuous design within your code.

 

Improved Unit Testing

 

Let’s look at the usage of mock objects applied to the desired qualities of a good unit test.

 

  • Unit tests should be atomic.  TDD style unit tests should be small tests that cover a specific, granular area of the code.  The code under test might interact with other classes or external systems, but at the moment you only want to worry about the proper functioning of the class under test.  You can preserve the atomicity of the unit test by replacing the external resources and coding dependencies by using a mock object to establish an expected behavior.  You specify exactly how the mock object is going to behave, so any unit test failures are now traced to the class under test.  When I was an engineer one of the hardest tasks in any engineering calculation was modeling boundary conditions.  A boundary condition is a point in the system with known behavior.  Inside your calculation you could ignore anything outside the boundary conditions.  The way to make your life easier was to establish boundary conditions so as to minimize the number of variables within any engineering calculation.  Mock objects are conceptually the same thing as boundary conditions.  One of the primary claims for the efficiency of TDD is the radically reduced time spent debugging code.  My experience that claim is true, but only when you write fine-grained tests.  My ratio of debugging time to coding time dropped precipitously when I started to become proficient with mock objects.  Please be aware that excessive mocking calls in a unit test can lead to unit tests that are too tightly coupled to the internal implementation of the very dependency you’re trying to mock.  This can make your code very difficult to refactor because the unit tests are brittle.
  • Order Independent and Isolated.  You should never assume that the tests are run in any certain order.  Each test should start from a completely known state and clean up after itself if necessary.  One of the biggest mistakes in writing unit tests is allowing state or the results of one unit test effect a different unit test.  It’s hard enough to troubleshoot testing failures.  Having to look through other unit tests to find the problem is time intensive and counterintuitive.  Static properties, singletons, and repositories are a common culprit, but the worst culprit might be testing against the database.  The entire purpose of a database is to maintain state, and that’s not a particularly good trait inside a unit test.  Using a mock object in place of any kind of stateful dependency will isolate your unit test from external state and make your unit tests order independent and isolated.
  • Intention Revealing.  This quality goes back to interaction based testing.  If the responsibility of the class being tested is to direct or coordinate other classes, then using a mock object inside the test may make the test easier to understand.  On the other hand, excessive mock object setup may make the unit test a lot more difficult to understand.  My advice is to simply pay attention to what you’re coding.  If it feels like using a mock object is making the test harder, back up and find a different way to write the test or change the class structure.    I’m going to come back to this topic quite a bit more in a later post.  I got pretty irritated at a junior/junior pair last year when I found out they had spent the better part of a day trying to write a unit test by mocking ADO.Net with no real success.  When I saw what they were doing I convinced them to change direction and create a new coarse-grained interface that would encapsulate the ADO.Net calls and would be easy to mock.
  • Easy to Setup.  This quality might be a bit in the eye of the beholder.  I’ll talk about this in much more detail in the next post or two, but a lot of mock scaffolding in a unit test is a code smell.  One very significant reason to use mock objects is to avoid the need to setup external resources into a known state for each test.  Think of a database.  You might only need a particular row in the database for the test, but due to the (necessary) evil of referential integrity that one row might require a whole bunch of other data first.  Even worse is something like a web service, a messaging queue, or the all time worst IMO – Active Directory.  More specifically, here’s a list of reasons to forgo trying to setup an external resource to behave in an expected way:
    • It’s often more work to write the SQL scripts than it is to setup the mock expectations or stub returns.  Less work is always good
    • Setting up the external state often obfuscates the test and can make the test harder to understand
    • Having external resource setup inside an automated test often tightly couples that test to the inner workings of the external dependency.  Loose coupling in automated tests is every bit as important for success as loosely coupled code.
  • Runs Fast.  Making your automated tests run quickly isn’t a luxury, it’s a necessity.  Except for the very beginning of a project you should expect automated testing to be the performance bottleneck in your automated build process.  It’s not a good thing when you start frequently hearing the phrase “we’re in CC.Net time.”   I had a post on this a while back here.

 

 

 

Designing for and with Mock Objects

 

I love the “mock as spy” analogy, but here’s an additional way to think about the role of a mock object.  In the movie and TV industries child actors are expressly limited in the number of hours they’re allowed to work in a day or week.  The director will use adults of roughly the same size to be “stand-ins” for the child actors so they can accurately storyboard the scene with the set, the lights, and the camera angles (I know all about this because of a classic Seinfeld episode years ago).  The director and the camera crew can get the scene completely setup without cutting into the child actors’ limited quota of hours.  Mock objects can be used in much the same way.  It’s what I like to think of as “Client First Development.”  Falling back on the Model View Presenter pattern as an example yet one more time, you might build a screen in a couple pieces:

 

  1. Presenter – handles the user information flow logic and intermediates communication between the actual screen and the backend services
  2. IService/Service – the gateway to the backend business or service layer
  3. IView/View – The actual screen

 

In this case I would define Presenter as the client of the services provided by the IService and IView interfaces.  I’ve consistently found it to be more efficient to make the development of the Presenter (the client) drive the signature of the IService and IView interfaces.  The Presenter is largely coded first with the dependencies mocked.  I’ve found this approach to be consistently more efficient than trying to drive the development from backend to front.  The requirements of “service provider” classes or modules are completely determined by the needs of their clients.  Building a service provider before the client will very frequently result in rework to the service provider when you discover that the client has different needs than you previously expected.  By using mocks or stubs I can narrowly focus on the design of the client and then turn and implement the resulting interfaces for the service provider.  Yeah you can give me the tired old line of “if you just did more research upfront…” but no design can ever accurately said to be “done” until it’s fully implemented and tested.

 

Another way to think about mock objects is that they’re like doing a UML sequence diagram, but in code. 

 

I’ve sarcastically described TDD in the past as Mock-Driven Design, but it does work.  You need to very consciously consider testability in almost every design decision.  Very purposely consider how to spread responsibilities between classes to maximize testability.  I am very much cognizant of utilizing mock objects when I do class and namespace level design.

 

 

Here’s a quote from Jeffrey Palermo this very afternoon – “do you know how nice it is to get a piece of code into NUnit or the debugger without having to install every single other service?”  Yes Jeffrey, I know exactly how you feel.

 

What to Mock?

 

So we come to the question of what to mock?  My rule of thumb is to mock anything that is involves any kind of call or access to things outside of the AppDomain.  Mocking the data access layer when you’re testing business or service layer logic is an obvious example.  Here are some other examples that I can remember using:

 

  • WinForms code
  • ASP.Net objects – user controls, HttpContext objects (but I’d advise against doing this directly)
  • Web service proxy classes.  Absolute no-brainer. 
  • Database access code, persistence
  • Active Directory access
  • Gateways to weird legacy code or systems – and almost all legacy code IS weird
  • Facades to other subsystems
  • Remoted classes

 

 

Next up is a discussion on the best practices for mock objects, including a section on when NOT to use mock objects.


Posted Tue, Dec 20 2005 4:22 PM by Jeremy D. Miller

[Advertisement]

Comments

Ayende Rahien wrote re: Why and When to Use Mock Objects
on Tue, Dec 20 2005 6:03 PM
You may also want to talk about the exepctations granuality.
It's easy to overly specify the expectation, making the test very brittle to changes in the code.
Jeremy D. Miller wrote re: Why and When to Use Mock Objects
on Tue, Dec 20 2005 6:18 PM
Ayende,

I hear you perfectly. I've burned myself a couple times with granular expectations. I'm going to try to demo just that when I talk about constraints and best practices.
the blog of michael eaton wrote Link Dump for Wednesday, December 21, 2005
on Wed, Dec 21 2005 10:01 AM
Daren Desjardins wrote re: Why and When to Use Mock Objects
on Thu, Dec 22 2005 2:03 PM
You have been making some great points.

For a thorough and excellent discussion of these topics, also check out

Working Effectively with Legacy Code
Michael Feathers
http://www.amazon.com/gp/product/0131177052/qid=1135278121/sr=8-1/ref=pd_bbs_1/002-6398087-0807246?n=507846&s=books&v=glance
Jeremy D. Miller wrote re: Why and When to Use Mock Objects
on Thu, Dec 22 2005 2:19 PM
Daren,

Thanks for the comment. Our little dev organization has all read the Feathers book. I'd second the recommendation.
Ben Hale wrote re: Why and When to Use Mock Objects
on Sat, Dec 24 2005 2:58 PM
I know you're not a Spring.NET guy and to be honest, as a Java guy I'm not entirely sure this is even in Spring.NET yet, but it's definiately one of the coolest things I've seen in testing in a while. There is a class called AstractTransactionSpringContextTest in the spring-mock area. Basically this class uses the setup and teardown methods to open a jdbc transaction and roll it back after the test. There are a couple of major benefits to this behavior. The first and most obvious is that if every single transaction is rolled back, and data that is ever written to the database, is never visible by anyone else. This means that even when using a shared database for testsing, there is no way that the data ever changes beyond the initial state; as long as the initial state can handle all tests, you never have to touch the database. The second and just as nice benefit is speed. In pretty much any RDMS these days, a rollback is pretty much instant therefore at the end of the test, not only do you not have the time penalty for the commit to the database, but you also don't have to pay any penalties to actually cleanup the database at the end. We've ended up using this with great success in code that uses hibernate. Basically we see that we pay a minor penalty bringing the BeanFactory to life at the beginning of a test suite, but after that each tests runs just as fast as if it was a unit tests (minus network overhead of course).
Sam Gentile's Blog wrote New and Notable 89
on Fri, Dec 30 2005 12:26 PM
Jeremy D. Miller -- The Shade Tree Developer wrote Best and Worst Practices for Mock Objects
on Tue, Jan 10 2006 6:01 PM
Mock objects are like any other tool.  Used one way they’re a huge time saver.  In other cases...
Mike Bria wrote re: Why and When to Use Mock Objects
on Sat, May 6 2006 6:03 PM
I just came across this thread today.  I work on a very large distributed html/java/sql-based application that, in a nutshell, supports the business of hospitals.  The project is close to eight years old, as is the many millions of lines of code and many hundreds of database tables.  The point -- it's BIG. Just recently, my organization has gone Agile [or, at least, is in the process :)]. I've got a great handle at this point on the fundamentals of unit testing / design (small, isolated tests leveraging mocks [we use JMock], Dependency Injection, Single Responsibility Principl, etc, etc, etc) and that's spreading well.  On the other hand, I've been having a harder time trying to get my head around how to implement good developer acceptance tests (using FitNesse) in my environment because of the massive model/service dependencies across the application.  These dependencies make ideal setup of a FitNesse test (one which is relatively simple, explanatory, clear, etc) a real daunting task, a near impossibility.  So, my thought (and question) is this:  is it okay for me to apply "faking" principles at a service level?  In other words -- I'm testing service 1, which, among a bunch of other little details, queries service 2 and posts a command to service 3.  Can my test fake Service 2 & 3 and still be a valid Acceptance (or, what I prefer to call "Service") test?
Jeremy D. Miller -- The Shade Tree Developer wrote Acceptance Testing - "Under the Skin" or using Stubs, is that Okay?
on Thu, Jun 8 2006 3:50 PM
From Why and When to Use Mock Objects, Mike Bria asks:
...So, my thought (and question) is this: is...
James Carr wrote re: Why and When to Use Mock Objects
on Wed, Jun 28 2006 12:25 AM
Great post. I use mocks religously ... I believe that if an object is not directly tied to the unit you are testing, it should be mocked out. Of course this is an area of disagreement with some, as I think that unit tests for DAOs, for example, should use mock connection and mock resultsets using recorded data, while others think testing the ability to hit the database is part of the test.

My question is, when is it acceptable to use mocks in acceptance tests?
Mike Bria wrote re: Why and When to Use Mock Objects
on Thu, Jul 6 2006 8:14 PM
Jeremy --
 Hoping you would have posted an opinion on my question - it appears you may have (?) started, but then nothing follows.  Do you have one?  I'd love to hear it.  Thanks bud...
Jeremy D. Miller wrote re: Why and When to Use Mock Objects
on Fri, Jul 7 2006 9:30 AM
Sorry about that Mike.  I made a separate post for that --> http://codebetter.com/blogs/jeremy.miller/archive/2006/06/08/146233.aspx

The comment up above should link to the new post as well.

The short answer is that I think you're approach is perfectly justified, and I would hope so because we do the same thing to test our messaging broker component workflow against 3rd party web services.
Jeremy D. Miller wrote re: Why and When to Use Mock Objects
on Fri, Jul 7 2006 9:32 AM
James,

Sorry I missed your comment.  I'm going to come down very hard on the subject of mocking connections/resultsets/data readers.  The effort to reward ration is all wrong.  It's too much work and leads to ugly looking tests that aren't readable.

My money is on mocking an interface to the DAO itself, and testing the DAO against the database itself.

Jeremy
Jeremy D. Miller -- The Shade Tree Developer wrote Best of the Shade Tree Developer (with actual links!)
on Mon, Aug 7 2006 4:51 PM
Between being extremely short handed at work, tech' reviewing a new book, a
possible book proposal...
Jeremy D. Miller -- The Shade Tree Developer wrote Best of the Shade Tree Developer (with actual links!)
on Fri, Sep 1 2006 2:33 PM

Between being extremely short handed at work, tech' reviewing a new book, a possible book proposal

Jeremy D. Miller -- The Shade Tree Developer wrote Jay's TDD QuickStart, and the underlying problems he stumbled into
on Wed, Mar 7 2007 2:06 PM

Jay Kimble , CodeBetter's resident AJAX guru, issued a little challenge to us TDD bloggers about using

Dim Blog As New ThoughtStream(me) wrote Excellent List of TDD Starter Blog Posts
on Wed, Mar 7 2007 5:05 PM

Jeremy Miller has posted quite a response to a question asked by Jay Kimble on unit testing with the...

Chad Myers' Blog wrote Starting a new set of projects, what to do?
on Mon, Oct 29 2007 3:59 PM

Starting a new set of projects, what to do?

Jeremy D. Miller -- The Shade Tree Developer wrote Design and Testability
on Wed, Dec 10 2008 12:25 AM

My most recent Patterns in Practice article entitled Design for Testability is available in this month's

Community Blogs wrote Design and Testability
on Wed, Dec 10 2008 12:37 AM

My most recent Patterns in Practice article entitled Design for Testability is available in this month's

Business Blog - Website Design | Internet Marketing wrote Business Blog - Website Design | Internet Marketing
on Mon, Apr 13 2009 2:12 AM

Pingback from  Business Blog - Website Design | Internet Marketing

About stubs, fakes and mocks « Hungry for Knowledge wrote About stubs, fakes and mocks « Hungry for Knowledge
on Wed, Sep 2 2009 3:35 PM

Pingback from  About stubs, fakes and mocks « Hungry for Knowledge

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us