Thursday, November 13, 2008

EasyMock gotcha: you can't use argument matchers as return value

I was getting some really nasty error messages while running my unit tests. A test that used EasyMock (using 2.0) failed but it wasn't anything in the actual test, it was caused by a test that ran before it. When skipping the test case the next test case using EasyMock would fail.

The error I was getting:
java.lang.IllegalStateException: 2 matchers expected, 1 recorded.
at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:41)
at org.easymock.internal.ExpectedInvocation.(ExpectedInvocation.java:33)
at org.easymock.internal.ExpectedInvocation.(ExpectedInvocation.java:26)
at org.easymock.internal.RecordState.invoke(RecordState.java:63)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:24)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:45)
at $Proxy88.handleRequest(Unknown Source)


First off, to find the offending test I build a test suite and reduced the tests run to isolate the tests where the error occurred until I had found the one causing the problem.

The code looked like this:

JdbcOperations jdbcOperationsMock = createMock(JdbcOperations.class);

// Expect query to use supplied alternative schema
expect(
jdbcOperationsMock.query(
eq("SELECT ARTICLE_SKU, ARTICLE_NAME FROM alt_schema_subs.tomtomtbarticle;"),
isA(RowMapper.class))
)
.andReturn(isA(List.class));


Which seems to be ok. The only problem was that I was using a argument matcher on a return value (see documentation). The solution was to supply a normal return value:

expect(
jdbcOperationsMock.query(
eq("SELECT ARTICLE_SKU, ARTICLE_NAME FROM alt_schema_subs.tomtomtbarticle;"),
isA(RowMapper.class))
)
.andReturn(new ArrayList<Object>());


And now the tests succeed.

Hope this was helpful. I intent to update the blog with more day-to-day problems in hope some people might find it on google.