XpdWiki

FrontPage
RecentChanges
XtC
FindPage
PageIndex
XpApprentices

Set your name in
UserPreferences

Edit this page

Referenced by
AaronOldfield
StrutsTestCase
MockMakerFAQ
AutomatedMockObje...
MockMaker.old
MockObject
XtC20020212
VisitorsBook
TestsMustCommunic...
Xtc20030617
DynaMock
OliBye_blogentry_...
PartialMocks
FourTypesOfTest
XtC20010904
DoingTests
XpDay
RonJefferiesOnMoc...
XpDay2Speakers
WhatsInAnInterfac...
MockObjectsCoding...
Xtc20030513
XtC20010529
MockMakerChanges1...
XtC20020108
PaulN
OpenSourceProject...
XpdBlog
IanSykes
TimMackinnon
...and 25 more




JSPWiki v2.0.52


MockObjects


The original version of the paper that documents MockObjects can be found at: http://www.mockobjects.com/endotesting.html

MockMaker creates MockObjects from Java Interfaces.

MockObjects infrastructure code can be found at http://www.mockobjects.com

MockObjects libraries for other languages: MockObjectsPython, MockObjectsRuby

For RonJefferies take on MockObjects see: RonJefferiesOnMockObjects

For MartinFowler on MockObjects see: http://martinfowler.com/articles/mocksArentStubs.html.

A thought. Extensive use of MockObjects allows the testing of the system to test PreConditions as well as PostConditions? and Invariants of classes. PreConditions are an area that is not well served by 'standard' Unit Tests. --TomAyerst

That sounds weird to me. Surely you test in the presence of PreConditions, rather than actually testing them? That said, MockObjects make them easier to set up and more explicit. --SteveF

Hmm, not sure now. In Design ByContract? there are postconditions and invariants (that it is the responsibility of the called class to ensure) and preconditions (that it is the responsibility of the calling class to ensure).

The thought was that, without putting precondition assertions in the system code, you can test that a calling object ensures that the called object is in the correct by putting in a mock called object in place with the requiste expectations. Standard tests only check that the tested object performs its part of the contract properly and ends up in a valid state. Are we agreeing or have I missed something? --TomA


I've moved a discussion here from Egroups on UnitTestingAroundThirdParties --SteveF


There is a new article on EarthWeb? about Cactus discussing (a little) Mock Objects and In-Container testing (http://softwaredev.earthweb.com/java/article/0,,12082_793701,00.html). I'm sorry if everything written is not accurate or not complete but bear in mind that it was written by a journalist ... ! :) (nah, just kidding)

--VincentMassol


Something I miss in most MockObjects discussions: MockObjects are easy to use if your class only uses objects passed as parameters. But what about objects that are owned/created inside the class under test? Unless the objects are created using some kind of factory method that you can override, it's near impossible to swap in the MockObject. That's the main reason stubs normally are swapped in at compile time.

I've found that the best approach is to use factories which you pass in to the object which needs to create other objects. This make it easy to swap in other implementations mock or other wise and it allows you to test that the internal objects are being created. i.e. your passing in the right arguments, creating the right number of objects. I've also found that is can help with memory management e.g.

public void createMyObject(...){
    try{
        new MemoryHungryObject(...);
    }catch(OutOfMemoryError e){ // Usually it's a really bad idea to catch this
        // eek. not memory. ask some memory manager object to try
        // releasing some objects (probably in Hash Maps)
        cacheManager.release();
        new MemoryHungryObject(...);
    }
}

The MockObject project is starting to produce factories for standard Java objects like java.io.File so that mock implementations can be used. It doe's mean we have to create proper interfaces for object to though. Hence the creation of alt.java.io.File, alt.java.io.FileImpl? with allow us to use com.mockobjects.io.File woo hoo

-- JeffMartin

I've used MockObjects a lot in C++ (and like them) and it is tempting to include "test-only" methods in your class that allow you to swap in the MockObject. But that's not a nice solution.

Do you encourage a programming style where objects have no members but only use parameters? Looks like a very restrictive version of the DemeterLaw?...

Any comments? --ErnestoGuisado

Quite often we might add, say, an extra constructor that accepts one of the internal objects. The default constructor will create a real instance. In practice, this doesn't hurt very much and sometimes proves really useful. We also tend to write more factory objects than is common but, again, that often proves useful after the fact. I can imagine this being especially true in C++. We also keep our classes small, so we tend to avoid too many instance variables. --SteveF

In some languages, you can pass mock objects as arguments to the constructor that have default values which create the real objects. So the common case initialises the object correctly, but passing in constructor arguments overrides that initialisation and allows mock objects to be used instead. E.g. in Python:

  class Reactor:
      def __init__( self, event_queue = System_Event_Queue() ):
          self.event_queue = event_queue
      
      def run( self ):
          while 1:
              event = event_queue.wait_for_event()
              if event.type == EVENT_QUIT:
                  return
              else:
                  dispatch_event( event )

  # Create a reactor that dispatches events from the system event queue
  reactor = Reactor()
  
  # Create a reactor that dispatches mocked events
  mock_queue = Mock_Event_Queue()
  reactor = Reactor( mock_queue )

---

Saw a nice article on using mock objects with Aspect-J on IBM developer works (http://www-106.ibm.com/developerworks/library/j-aspectj2/index.html) -- VanEmmenis (28-Aug-02)

---

Here's a plug for NMock (http://nmock.truemesh.com/) - a very simple to use dynamic mock object library.³host³³date³February 18, 2003³agent³Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2.1) Gecko/20021130³MockObjects


Refactoring code to accomodate tests has always seemed to me to be somewhat counter intuitive. Whilst I am a believer in design by testing, I would shy away from considering tests as the end goal. Tests should validate the fulfilment of requirements, not define them. When we sat down to write AgileTest, there were a number of shortcomings in existing mock object implementations (no offence intended to anyone) that seemed to fuel the dislike of mock objects among certain folk:
  • Source-based mocks introduce additional artefacts to a project, increasing complexity, effort and maintenance
  • Source based mocks generally require access to source code
  • Java proxy-based mocks are limited to Interfaces
  • Both source and proxy based mocks are limited to parameterized collaborations
By working at the bytecode level, we have managed to overcome all of these constraints. We use a proxy mechanism for interfaces, but for classes we are able to emit Imposters - clones of the mocked class with behavioural methods injected. Taking it a step further, we use object substitution - the transplanting of donor code from Imposters into the class under test, replacing references to the class to be mocked, to create Interlopers. Interlopers provide non-intrusive mocking of complex, non-parameterized collaborations. There's no need to refactor code to satisfy the constraints of the testing framework.
\ There's an article here that describes the approach in more detail.
\ (a blatant plug by) Rupert
See also: DynaMock
A very neat solution to the problem of using mock objects that are not passed in to the object under test (because they are created/obtained inside the class) is to use a method outlined in this developerworks article http://www-106.ibm.com/developerworks/java/library/j-mocktest.html.

For the past few weeks I have been combining the technique of "Extract the creation code into a (protected) factory method, override this factory method in a test subclass (anonymous inner subclass), and then make the overridden method return a mock object instead. Finally, if practical, add a unit test that requires the original object's factory method to return an object of the correct type".

At Wordtracker we occasionally use an automated system for overriding the factories which for want of a better name we have called PartialMocks. Sometimes I like to refactor the code a little rather than add the extra logic from optional parameters. -- MarcuS


This approach seems excellent especially when combined with the new Dynamic MockObjects introduced to me by TimM and SteveF. I have used it writing EJB Apps without a App Server - incredibly useful as well as when writing components for middleware, when a lot of the collaborations are usually heavy weight and server-dependant. -- DanPollitt


Inserting Mocks: The Simplest Approach?

How about using reflection to slip mocks into place as part of the test setup? For example:

import junit.framework.TestCase;
import java.lang.reflect.Field;

public class AccessControlTest extends TestCase
{
    public void test_renamePerson() throws Exception
    {
        Person person = new Person("Miles Daffin");
        String newName = "Daffy Duck";
        String fieldName = "_name";

        Field nameField = person.getClass().getDeclaredField(fieldName);
        nameField.setAccessible(true);
        nameField.set(person, newName);
        assertEquals("value of field " +fieldName, newName, person.getName());
    }
}

class Person
{
    private String _name;

    public Person(String name)
    {
        _name = name;
    }

    public String getName()
    {
        return _name;
    }
}

It is a simple matter to build a test utility class to handle this task, and I think it is better than the AspectJ approach because it involves
less 'infrastructural fannying about' (AspectJ, Ant taskdefs etc). However, the aspectj approach is more flexible.--MilesD

I think the simple answer to that is "Expectations". I.e the Mock isn't just there for show, you verify it at the endWe originally came up with the name MockObjects but discovered the power is in Expectations. The DynaMock library is IMHO the best implementation of this.

(Does the previous comment belong in this section? If so then I don't understand how it relates to my suggestion for inserting mocks. The test case is there to prove that the value of the _name field has been reset, not as a demo of using the approach with a mock... --MilesD)

I have used junit-addons PrivateAccessor? utility to do exactly this (http://junit-addons.sourceforge.net/) but in terms of preference it sits behind either refactoring to push in the dependency via a constructor or using an internal factory method (protected) that I override in the test using an anonymous class. --DanPollitt

Could you explain your preferences a little? --MilesD


However...

I feel that there is an assumption around here that MockObjects are a good thing, no question.

  • Conventional unit tests test what a class does: "when I ask the cook for an omlette I expect an omlette".
  • MockObjects test how a class does: "when I ask the cook for an omlette he should access the fridge once and only once".

Mock based tests can be a real pain to maintain, e.g. during refactoring. The cook makes a fine omlette but employs a Kitchen Porter (KP) and
stops going near the fridge. The KP raids the fridge for snacks which causes only the mock based tests to fail. But, surely the important
things to check are that the cook can cook, and that the kitchen is efficient (e.g. maximum order time not exceeded and no 'food leaks' because
KPs snack too much). So I write tests to check that the average order times and the 'food in: orders out' ratio are within tolerances.
If these break I can put the debugger on the code and see which threads access the fridge etc.... Basically, I think mock based tests should be
used sparingly. --MilesD

Miles I'm not sure I agree ;-). I think you're reinforcing the need for Mocks. The mock object is telling you that you've modeled the roles and responsibilities incorrectly in the first place. The fridge should not be part of the cooks contract. The mock test being "a pain to maintain" is a CodeSmell? telling you that you need a cook fridge mediator (the KP). This is TestFirstDesign, if the "once and only once fridge access" is important then the mock test embodies that, good start. It was your choice to make the cook part of it. Feel good that you wrote the correct test.

What were you really testing?, I don't think it was the cook or the fridge, I think it was the IPreparationStrategy? (of which KitchenPorter? is an implementation). Nobody would have thought of that to start with, but to blame Mock objects for forcing you into further (IMHO valid) decomposition seems unfair.

You're story seems to be "maximum order time not exceeded and no 'food leaks'". However there's no talk of proof that you have a maximum, no talk of optimisation or solving that story mathematically. Without an IPreparationStrategy? how can you ever start being extreme (for example) ploting the averages for various implementations of the strategy, or really going for it and training genetic algorithms using your test in some mock kitchen. This is actually what you need to be testing to proove you've delivered that story. Cook and fridge were a bad start, they had so much pressure on them to be something other than a couple of lines of code. Until know I actually imagined they could cook me an omlette. Lobster Quadrille anybody?-- OliBye

Excellent Oli! I see I have some thinking to do, not to say learning. Good stuff.

"Training genetic algorithms" eh? What does this involve? (Beyond a top hat, large moustache, chair and whip?) --MilesD


Edit this page   More info...   Attach file...
This page last changed on 02-Jun-2005 11:20:04 BST by OliBye.