Returning Parameters in JMock 2

If you have a method like:

String getParameter(String name, String defaultValue)

where defaultValue is returned if the parameter isn’t specified, it can be challenging to get the right behavior in JMock without just hard coding what the defaultValue should be. Fortunately, a custom match which doubles as an Action can solve this pretty easily:

import org.hamcrest.*;
import org.jmock.api.*;

public class CapturingMatcher<T> extends BaseMatcher<T> implements Action {
	public T captured;

	public boolean matches(Object o) {
		try {
			captured = (T)o;
			return true;
		} catch (ClassCastException e) {
			return false;
		}
	}

	public void describeTo(Description description) {
		description.appendText("captured value ");
		description.appendValue(captured);
	}

	public Object invoke(Invocation invocation) throws Throwable {
		return captured;
	}
}

It can then be used like:

context.checking(new Expectations() {{
	CapturingMatcher<String> returnCapturedValue = new CapturingMatcher<String>();
	allowing(mockObject).getParameter(with(equal("expectedParameterName")), with(returnCapturedValue)); will(returnCapturedValue);
}});

The matcher is used both for the parameter value (which it stores) and the return action, so it acts like a back reference would in a regex. The same class be be useful alone as a matcher to let you interrogate the parameter value using normal assert statements rather than building a custom matcher.

I really should investigate what the describeTo function really should do though – I’m sure it would generate pretty weird messages at the moment.

4 Responses to “Returning Parameters in JMock 2”

  1. Nathan Says:

    Slightly off topic, but from this post note that you’re using Jmock for mocking framework. Have you ever looked at Mockito? http://code.google.com/p/mockito/

    I’ve found it’s much more intuitive than other mocking frameworks. Supports hamcrest as well, so with similar CapturingMatcher def as you’ve got (implementing Answer instead of Action), you would end up having something like:

    when(mockObject.getParameter(eq(“expectedParameterName”), argThat(returnCapturedValue )).thenAnswer(returnCapturedValue);


  2. Adrian Sutton Says:

    Yeah I’ve seen Mockito, there’s not really enough that’s better to justify rewriting everything. JMock 2 has a very friendly syntax, with the only weird bit being the context.checking wrapper. I think the JMock API is actually much easier to read than Mockito in many ways, mostly because it uses full words (equal instead of eq) and better matching normal lingo – e.g. will(returnValue(…)) instead of thenAnswer since Java returns things it doesn’t answer.

    It’s all much a muchness though.


  3. Steve Freeman Says:

    Thanks for posting the tip. describeTo() is intended to help you understand what has happened when it goes wrong.
    I’m curious, though, as to why this trick is necessary in a unit test. Surely you know what the expected default value should be?


  4. Adrian Sutton Says:

    I suppose you could assert that it’s passing in a specific default value just as easily and then you’d know what to return, but that defines more about the implementation than I think a test really should (at least in this case). I probably would have just done that if I didn’t already have the capturing matcher around to make my life easier with complex asserts. In this case the mock is half stub/half mock so I want to be as loose as possible in what method calls and arguments are used (mostly) and just assert that the result is correct.


Leave a Reply

(Valid OpenIDs will skip moderation)

Alternatively, subscribe to the Atom feed.