mockito 1.5 and spying on objects

Mockito is a Java Mock objects framework which seems more usable than either of the main contenders (JMock and EasyMock). The project has just released a new version which now allows the attachment of a mock “overlay” to an existing object.

This has been on my “evaluate” stack for months, but (as Harry Pynn pointed out when he “vouched for” me) I tend to be more comfortable with “classic” TDD and don’t usually find much use for Mock Objects.

I have had a quick play with the examples of use on the Mockito site with mixed success. many obvious cases work well, but there are also some gaps in the way it works. For example, consider this small example test:

import static org.mockito.Mockito.spy;
 
public class PlaypenTest extends TestCase {
	public void testMockito() {
		List real = new ArrayList(); 
		real.add("first");
		real.add("second");
		List ml = spy(real);
 
		stub(ml.get(0)).toReturn("huh");
		assertEquals("huh", ml.get(0));
		assertEquals("second", ml.get(1));
	}
}

It works correctly. However, the following idiomatic and functionally similar simplification throws a complicated internal exception in the “spy” method.

import static org.mockito.Mockito.spy;
 
public class PlaypenTest extends TestCase {
	public void testMockito() {
		List real = Arrays.asList(new String[] {"first", "second"});
		List ml = spy(real);
 
		stub(ml.get(0)).toReturn("huh");
		assertEquals("huh", ml.get(0));
		assertEquals("second", ml.get(1));
	}
}

Maybe I’ll get around to using it for something. I’m still not sure.

mockito – Google Code

3 Comments

  1. The spy mechanism is implemented with runtime subclassing. The exception occurs because the second example is trying to spy on a private inner class (Arrays.ArrayList) that can’t be subclassed. Mockito should probably detect this condition and throw a more meaningful exception.

  2. Thanks for the analysis, Steve.

    I have never really liked the idea of private classes (and I like final classes even less!) especially when they cause this sort of problem.

    Unfortunately, the Arrays.asList(new Thing[] {…}) trick is the nearest thing I have so far found to a collection literal in Java, so I would be loath to abandon it just in case I might need to mock the results.

    Java sure can be frustrating sometimes.

  3. If you use more of the Java 5 features you can achieve both goals. For example,

    List real = new ArrayList(asList(“first”, “second”));

    instead of …

    List real = Arrays.asList(new String[] {“first”, “second”});

    It’s even nicer if you use a simple static generic method to wrap the list creation.

    private static List list(T… items) {
    return new ArrayList(asList(items));
    }

    Then you can create lists very succinctly.

    List data1= list(“first”, “second”);
    List data2 = list(1, 2, 3);

    And you are still compatible with mocking techniques that use runtime subclassing.

    Just some ideas…

Comments are closed.