Thursday 21 January 2010

EasyMock gotchas

1. Using Easymock matchers when passing in known values to mock classes.

When we get errors like:

java.lang.IllegalStateException: 2 matchers expected, 1 recorded.
at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:42)
at org.easymock.internal.ExpectedInvocation.<init>(ExpectedInvocation.java:34)


It means we are missing a matcher for our mocked classes.

Take this code, for example:

Map<String, Object> params = new HashMap<String, Object>();
List<Integer> groupIds = Arrays.asList(1,2,3);
params.put("groupIds", groupIds);

expect(mockSimpleJdbcTemplate
.queryForList((String)anyObject(), params))
.andReturn(results);


Replace the last line with:

expect(mockSimpleJdbcTemplate
.queryForList((String)anyObject(), eq(params)))
.andReturn(results);

"If you would like to use matchers in a call, you have to specify matchers for all arguments of the method call."

Otherwise, it should only be known values.

If you are mixing known values with matchers, you will have to use the eq() ("equals) static method

See: http://www.easymock.org/EasyMock2_2_Documentation.html


2. when mocking classes that are not an interface, like
SimpleJdbcTemplate, we need to use the createMock, replay, and verify
methods FROM org.easymock.classextension.EasyMock NOT FROM
org.easymock.EasyMock


otherwise, we get this error when running the test:

java.lang.IllegalArgumentException: not a proxy instance
at java.lang.reflect.Proxy.getInvocationHandler(Proxy.java:637)
at org.easymock.EasyMock.getControl(EasyMock.java:1440)
at org.easymock.EasyMock.reset(EasyMock.java:1397)


Update 11 November 2010:
You no longer need to do the easymock.classextension package in (2) if you are using EasyMock 3. The package and classes still exist in EasyMock 3 only for backward compatibility. See the documentation.