Mock Objects

If you have had it with codebases that drag along everything and the kitchen sink, (possibly using the Singleton) you must read this page. Classes that look up or instantiate heavyweight classes themselves are such beasts. As you might have experienced, they are a pain to test. (And ample proof that the authors didn't follow TDD ). Dependency Injection with PicoContainer and Mock Objects to the rescue!

Mock Objects are special objects used during testing. Mock Objects and classes that honour Constructor Injection are a perfect match, since such classes can be handed mocks during testing and "the real thing" when the application is run.

This illustration shows how:

Unit-Test Time Deployment Time

The class

Here is what NeedsStuff might look like:

public class NeedsStuff {
    // These are both interfaces.
    private final BlueStuff bs;
    private final GreenStuff gs;

    public NeedsStuff(BlueStuff bs, GreenStuff gs) {
        this.bs = bs;
        this.gs = gs;
    }

    public String doIt() {
        return bs.jump() + gs.beatIt();
    }
}

During test time we'll give NeedsStuff some mocks.

During prime time (when the final application is running), the NeedsStuff class will be instantiated with a SuperHeavyBlueStuff and a NuclearGreenStuff instance. These require some really heavy infrastructure such as database connections and network access. We don't want to drag along that when we test NeedsStuff! (It can wait till the integration test).

Test Time

Our test becomes like this:

public class NeedsStuffTestCase extends junit.framework.TestCase {
    public void testNeedsStuffDoesStuff() {
        BlueStuff bs = createBlueStuffMockThatReturnsBlahOnJump();
        GreenStuff gs = createGreanStuffMockThatReturnsHuhOnBeatIt();

        NeedsStuff ns = new NeedsStuff(bs, gs);
        assertEquals("BlahHuh", ns.doIt());

        // verify mocks.
    }
}

We are testing the doIt() method without having to drag along any heavy dependencies

We won't go into further technical details about mocks, as there are many libraries to choose from. Check out JMock, MockObjects and EasyMock.

Prime Time

It is left to PicoContainer to instantiate NeedsStuff. In order for it to succeed, we must also configure the container with some real BlueStuff and GreanStuff:

public class AppBootstrapper {
    public void runapp() {
        MutablePicoContainer pico = new DefaultPicoContainer();
        pico.registerComponentImplementation(NeedsStuff.class);
        pico.registerComponentImplementation(SuperHeavyBlueStuff.class);
        pico.registerComponentImplementation(NuclearGreenStuff.class);
    }
}

It is even possible to do this component wiring using a soft scripting language. See Nano Container

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Feb 19, 2004

    Tieying Liu says:

    Nice pictures. What do you use for the drawing?

    Nice pictures. What do you use for the drawing?

  2. Feb 20, 2004

    Aslak Hellesøy says:

    PowerPoint and exporting to PNG , then some resizing/cropping in any image edito...

    PowerPoint and exporting to PNG , then some resizing/cropping in any image editor.

  3. Feb 20, 2004

    Jon Tirsen says:

    Maybe we should have something a little bit more concrete here too? Instead of "...

    Maybe we should have something a little bit more concrete here too? Instead of "NeedsStuff". I know it's hard to find valid real examples but I think it's in the end worthwhile.

  4. Nov 10, 2005

    Mitch Christensen says:

    What method/design pattern should be used to access the PicoContainer? I get th...

    What method/design pattern should be used to access the PicoContainer?

    I get the creation of the PicoContainer, and constructor injection in general. However, I'm still a bit vague on how we are supposed to reference the (global?) PicoContainer when an object is needed. A singleton (anti)pattern comes to mind, but that doesn't seem right.

    In my specific case, we are using Axis, which instantiates the service classes with a no-arg constructor. How would I get the real-world (i.e. non-mocked) objects from PicoContainer in such a case?