Los Techies : Blogs about software and anything tech!

Auto mocking Explained


What does it do?

There is nothing fancy about an automocker. There is nothing scary about an automocker. An automocker is like one of those little classes we all write in order to quickly and easily create objects that we need for our tests. Nice, simple, helpful, non-threatening.

You tell the automocker which class you want to test, and the automocker creates an instance of that class for you. If the constructor of your class requires you to pass in other objects, the automocker will automatically create a mock for each of the necessary types and pass them in. The automocker will keep track of all the mocks it creates, and allows you to retrieve them if you need to stub a specific behavior.

Why should I fear the automocker?

Where it gets scary (for some) is when you use the name most often used to refer to them: auto mocking container. “Wait wait wait, you’re using an IOC container in your unit test?! Configuration! Brittle! No thank you!”

The name comes from AutoMockingContainer, which introduced the idea of an automocker (to me, at least) by using the Castle Windsor IOC tool to do the heavy lifting. The StructureMap IOC tool distribution also includes an automocker. But here’s the thing – the container is just an implementation detail. You, as the test writer, never have to know there is a container in play. Automocking is not an IOC container feature. Automocking is really a feature of a mocking framework, but just happens to be packaged and/or named in relation to a container.

In other words, I suspect the idea of automocking would be a lot less scary to people if it were packaged with the mocking frameworks. Suppose Rhino.Mocks added the method: MockRepository.CreateWithMocks<ClassToTest>() – would automocking still be as distasteful? Maybe it would use Castle MicroKernel under the hood, but you wouldn’t ever be exposed to it (just as Rhino.Mocks currently uses Castle DynamicProxy under the hood).

Why should I use the automocker?

Ok, so you’re over the container part. But you’re not convinced. The automocker can save you some tedious keystrokes, but code snippets solve that problem. I think the big benefit of the automocker is that it helps keep the content of your tests focused on the functionality being tested. It also helps keep your tests less brittle as your objects evolve.

Consider the following class that I need to test:

   1: public class PhotoController
   2: {
   3:     private readonly IPhotoCatalog photoCatalog;
   4:  
   5:     public PhotoController(IPhotoCatalog photoCatalog)
   6:     {
   7:         this.photoCatalog = photoCatalog;
   8:     }
   9:  
  10:     public PhotoDetails[] List()
  11:     {
  12:         return photoCatalog.FindAll();
  13:     }
  14:  
  15:     public void Save(PhotoDetails photo)
  16:     {
  17:         photoCatalog.AddPhoto(photo);
  18:     }
  19: }

A couple tests, without automocking, might look like this:

   1: [TestFixture]
   2: public class when_visiting_the_list_page
   3: {
   4:     private PhotoDetails[] Output;
   5:     private PhotoDetails[] AllPhotos;
   6:  
   7:     [SetUp]
   8:     public void Setup()
   9:     {
  10:         AllPhotos = new[] { new PhotoDetails(1), new PhotoDetails(2) };
  11:         IPhotoCatalog photoCatalog = MockRepository.GenerateStub<IPhotoCatalog>();
  12:         photoCatalog.Stub(c => c.FindAll()).Return(AllPhotos);
  13:  
  14:         var controller = new PhotoController(photoCatalog);
  15:         Output = controller.List();
  16:     }
  17:  
  18:     [Test]
  19:     public void should_display_all_of_the_photos_in_the_catalog()
  20:     {
  21:         Assert.AreEqual(AllPhotos, Output);
  22:     }
  23: }
  24:  
  25: [TestFixture]
  26: public class when_saving_a_photo
  27: {
  28:     private PhotoDetails thePhoto;
  29:     private IPhotoCatalog photoCatalog;
  30:  
  31:     [SetUp]
  32:     public void Setup()
  33:     {
  34:         photoCatalog = MockRepository.GenerateStub<IPhotoCatalog>();
  35:         var controller = new PhotoController(photoCatalog);
  36:  
  37:         thePhoto = new PhotoDetails(4);
  38:         controller.Save(thePhoto);
  39:     }
  40:  
  41:     [Test]
  42:     public void should_store_the_photo_details_in_the_catalog()
  43:     {
  44:         photoCatalog.AssertWasCalled(c => c.AddPhoto(thePhoto));
  45:     }
  46: }

The same tests, with automocking, would look like this:

   1: [TestFixture]
   2: public class when_visiting_the_list_page
   3: {
   4:     private PhotoDetails[] Output;
   5:     private PhotoDetails[] AllPhotos;
   6:  
   7:     [SetUp]
   8:     public void Setup()
   9:     {
  10:         AllPhotos = new[] { new PhotoDetails(1), new PhotoDetails(2) };
  11:         var mocks = new RhinoAutoMocker<PhotoController>();
  12:         var controller = mocks.ClassUnderTest;
  13:         mocks.Get<IPhotoCatalog>().Stub(c => c.FindAll()).Return(AllPhotos);
  14:  
  15:         Output = controller.List();
  16:     }
  17:  
  18:     [Test]
  19:     public void should_display_all_of_the_photos_in_the_catalog()
  20:     {
  21:         Assert.AreEqual(AllPhotos, Output);
  22:     }
  23: }
  24:  
  25: [TestFixture]
  26: public class when_saving_a_photo
  27: {
  28:     private PhotoDetails thePhoto;
  29:     private RhinoAutoMocker<PhotoController> mocks;
  30:  
  31:     [SetUp]
  32:     public void Setup()
  33:     {
  34:         mocks = new RhinoAutoMocker<PhotoController>();
  35:         var controller = mocks.ClassUnderTest;
  36:  
  37:         thePhoto = new PhotoDetails(4);
  38:         controller.Save(thePhoto);
  39:     }
  40:  
  41:     [Test]
  42:     public void should_store_the_photo_details_in_the_catalog()
  43:     {
  44:         mocks.Get<IPhotoCatalog>().AssertWasCalled(c => c.AddPhoto(thePhoto));
  45:     }
  46: }

Not a huge difference, mostly because the class under test only has a single dependency, so you are only hiding a single call to MockRepository.GenerateMock. But what about when I need to change some functionality on one of the methods? We realize we need to save a copy of the uploaded photo to the file system. We will need to change the Save method on the controller, and add a new dependency on an IFileSystem service.

We’ll update the automocked tests to include the new specification (no other changes to the tests required):

   1: [Test]
   2: public void should_store_the_photo_in_the_file_system()
   3: {
   4:     mocks.Get<IFileSystem>().AssertWasCalled(fs => fs.WriteFile(thePhoto.Filename, thePhoto.Data));
   5: }

And the corresponding code to:

   1: public class PhotoController
   2: {
   3:     private readonly IPhotoCatalog photoCatalog;
   4:     private readonly IFileSystem fileSystem;
   5:  
   6:     public PhotoController(IPhotoCatalog photoCatalog, IFileSystem fileSystem)
   7:     {
   8:         this.photoCatalog = photoCatalog;
   9:         this.fileSystem = fileSystem;
  10:     }
  11:  
  12:     public PhotoDetails[] List()
  13:     {
  14:         return photoCatalog.FindAll();
  15:     }
  16:  
  17:     public void Save(PhotoDetails photo)
  18:     {
  19:         photoCatalog.AddPhoto(photo);
  20:         fileSystem.WriteFile(photo.Filename, photo.Data);
  21:     }
  22: }

Now I can run all of my tests (for both Save and List) – they all compile and pass. Notice the only change to my tests was adding a single method that asserted the new behavior.

The tests that didn’t use the automocker? Not as lucky. I add the new method that has the new assertion,

   1: [Test]
   2: public void should_store_the_photo_in_the_file_system()
   3: {
   4:     fileSystem.AssertWasCalled(fs => fs.WriteFile(thePhoto.Filename, thePhoto.Data));
   5: }

and then I have to update the Setup to create the new mock. Not a big deal.

   1: fileSystem = MockRepository.GenerateStub<IFileSystem>();
   2: var controller = new PhotoController(photoCatalog, fileSystem);

The IDE complains because I’m trying to pass two arguments to the controller constructor, but it only takes one, so I update the controller. Still not a big deal. Try and run my test – ugh, compiler error. Looks like I need to update the tests for the List method? Why? I’m not making any changes to the List method? So I update the Setup for that test fixture as well:

   1: var fileSystem = MockRepository.GenerateStub<IFileSystem>();
   2: var controller = new PhotoController(photoCatalog, fileSystem);

Is it horrible? No. Is the automocked version nicer? I think so. The evolution of my code had minimal impact on the tests, plus I was able to eliminate “noise” code that creates all of the mocks. What does the automocked version cost me? Just an Add Reference to an assembly that I already have in the  tools/lib section of my source tree.

Neither my code nor my tests have any dependency on an IOC container. There is no external dependency or configuration. Even if I don’t use StructureMap in my application code, I could still use the RhinoAutoMocker that it includes for my tests. If my code DOES use StructureMap as its IOC container, I could still use the original Windsor-based AutoMockingContainer for my tests without a problem. The key point being that the IOC container you use in your application has nothing to do with the automocking you do in your tests.

Kick It on DotNetKicks.com
Posted Feb 03 2009, 08:25 PM by Joshua Flanagan
Filed under:

Comments

Michael A. Smith wrote re: Auto mocking Explained
on 02-03-2009 11:33 PM

I'm sold. Cheers!

chrissie1 wrote re: Auto mocking Explained
on 02-04-2009 2:22 AM

Yep me too.

Is this going to be part of the structuremap docu?

Jake Scott wrote re: Auto mocking Explained
on 02-04-2009 2:23 AM

Haha, thanks for sharing I have this exact problem on my current project because my controllers have many dependancies. Each time I introduce new dependancies I have to go through all my test code cutting and pasting the new Mock setup code.

Do you think the term AutoMocking is one of those terms that Scott is refering to here blog.scottbellware.com/.../teaching-symbology-and-intellectual_01.html

Anyway great post.

Reflective Perspective - Chris Alcock » The Morning Brew #279 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #279
on 02-04-2009 2:39 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #279

Łukasz Podolak wrote re: Auto mocking Explained
on 02-04-2009 4:02 AM

Excellent article, thank you for a great explanation.

David wrote re: Auto mocking Explained
on 02-04-2009 4:05 AM

Awesome post. Thanks for this!

Quick question: how do you handle injecting mocks vs. stubs using automocking? Or do you always use stubs and override where necessary?

DotNetShoutout wrote Auto mocking Explained - Joshua Flanagan
on 02-04-2009 5:57 AM

Thank you for submitting this cool story - Trackback from DotNetShoutout

Chris Allen wrote re: Auto mocking Explained
on 02-04-2009 6:20 AM

Awesome, I've been looking for more information on this for a while now. Thanks for the info.

Michael Hedgpeth wrote re: Auto mocking Explained
on 02-04-2009 8:19 AM

I do think this is cool, but...

Could it be your desire for automocking is covering up the need for a better design?  Maybe in this case you should rethink your dependencies.

Jeremy D. Miller -- The Shade Tree Developer wrote Great writing from my colleagues
on 02-04-2009 9:41 AM

The Dovetail gang is churning out material this week. Chad checks in with an article originally published

Dew Drop - February 4, 2009 | Alvin Ashcraft's Morning Dew wrote Dew Drop - February 4, 2009 | Alvin Ashcraft's Morning Dew
on 02-04-2009 10:58 AM

Pingback from  Dew Drop - February 4, 2009 | Alvin Ashcraft's Morning Dew

Joshua Flanagan wrote re: Auto mocking Explained
on 02-04-2009 8:21 PM

@chrissie1 Yes, this information will get into the StructureMap documentation (eventually...)

Joshua Flanagan wrote re: Auto mocking Explained
on 02-04-2009 8:25 PM

@Jake - I couldn't say if AutoMocking is one of the barrier words that Scott was referring to. But I don't think it matters in the context of this post, as I had a different target audience in mind than what he was referring to. I targeted developers who are already familiar with, and using a mocking framework, but a little skeptical of automocking.

Joshua Flanagan wrote re: Auto mocking Explained
on 02-04-2009 8:35 PM

@David - I can't speak for the Windsor-based AutoMockingContainer. The StructureMap RhinoAutomocker always creates mocks using the DynamicMock() method. If you need a specific fake to be a stub or static mock, you can manually create it and then use the Inject() method on the automocker so it knows to use it (works for concrete classes as well).

Joshua Flanagan wrote re: Auto mocking Explained
on 02-04-2009 8:39 PM

@Michael - it could be. But I'm comfortable assuming that any truly worrisome design smell will expose itself in a more impactful way than the automocker could disguise.

Brian wrote re: Auto mocking Explained
on 02-06-2009 6:42 PM

The one thing I have to say that auto-mocking does to the negative, and IoC in general, is for new people coming in there is a lot of 'magic' that they have to figure out that they have no tests to look to for guidance and have been simply stuck going through individual classes and going 'oh...there an overloaded constructor with a different/second argument type).

Not saying I disagree, just saying that's one of the problems I've seen people have, most I've worked with want to 'see it work'.

Code Monkey Labs wrote Weekly Web Nuggets #50
on 02-07-2009 11:07 PM

Pick of the week: You’re Doing It Wrong General Sorting Generic Lists Using IComparer<T>, IComparable<T>, and the Comparison<T> Delegate : John Miller explains the different options for sorting collections in .NET 3.5. Read the Diffs

Ian Cooper [MVP] wrote With Services the focus is on behavior
on 02-21-2009 10:09 AM

This post is really just tying together some ideas. A year ago I posted on my preference for classicist

Community Blogs wrote With Services the focus is on behavior
on 02-21-2009 10:28 AM

This post is really just tying together some ideas. A year ago I posted on my preference for classicist

Code Monkey Labs wrote Weekly Web Nuggets #50
on 02-22-2009 9:27 PM

Pick of the week: You’re Doing It Wrong General Sorting Generic Lists Using IComparer<T>, IComparable<T>, and the Comparison<T> Delegate : John Miller explains the different options for sorting collections in .NET 3.5. Read the

Joshua Flanagan wrote How we handle application configuration
on 07-12-2009 8:38 PM

We recently overhauled the way we handle configurable settings within our application (server names,

StevenHarman.net wrote Prefer Dependency Injection to Service Location
on 09-25-2009 6:30 PM

Prefer Dependency Injection to Service Location

Elegant Code » Unity/Moq – AutoMocker or AutoMockingContainer wrote Elegant Code &raquo; Unity/Moq &#8211; AutoMocker or AutoMockingContainer
on 01-03-2010 11:52 AM

Pingback from  Elegant Code » Unity/Moq – AutoMocker or AutoMockingContainer

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems