During suite tests EasyMock says 0 matchers expected 1 recorded

easymockmatcher

So I've been using EasyMock's class extension for a while now. All of a sudden I'm getting this exception, but only when I run the entire test suite:

java.lang.IllegalStateException: 0 matchers expected, 1 recorded.
at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:42)
at org.easymock.internal.ExpectedInvocation.<init>(ExpectedInvocation.java:34)
at org.easymock.internal.ExpectedInvocation.<init>(ExpectedInvocation.java:26)
at org.easymock.internal.RecordState.invoke(RecordState.java:64)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:24)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:56)
at org.easymock.classextension.internal.ClassProxyFactory$1.intercept(ClassProxyFactory.java:74)
at com.protrade.soccersim.data.emulator.matrix.PositionCategoryMatrix$$EnhancerByCGLIB$$c5298a7.getPossession(<generated>)
at com.protrade.soccersim.data.emulator.stats.team.PossessionCalculatorUnitTest.testDeterminePossessionHomeWin(PossessionCalculatorUnitTest.java:45)

The code involved is this little beauty (trimmed a bit):

    @Before
public void setUp() throws Exception {
    homeTeam = createMock( PositionCategoryMatrix.class );
    awayTeam = createMock( PositionCategoryMatrix.class );
    ...
}

@Test
public void testDeterminePossessionHomeWin() {
    expect(homeTeam.getPossession()).andReturn( 0.15151515 );
    expect(awayTeam.getPossession()).andReturn( 0.01515152 );
    replay( homeTeam, awayTeam );
    ...
}

The exception is being thrown on the first expect. And it really doesn't make sense. It says it's getting a matcher, but the method doesn't even take an argument. And odd enough it's only during test suites! I'm creating a new mock in the @Before, so it shouldn't be inheriting anything from somewhere else (not that some other method would have a matcher on it)

So, any ideas?

Best Answer

I was sick and tired of seeing this with each new legacy code base with EasyMock I had to work with. Write one new EasyMock test by the book and all of the sudden random tests start failing because of Matchers never captured. So I went looking how EasyMock stores those Matchers. It makes use of a final class LastControl, in that class are a few threadlocals where different things get stored. One of those was for the Matchers. Luck has it that there is a static method on there to pull all the Matchers from the threadlocal that where still on there. So this gave me this idea (with help of a collegue, thanks Sven, he wanted credit)

/**
 * Base class to make sure all EasyMock matchers are cleaned up.  This is not pretty but it will work
 * 
 * @author N069261KDS
 *
 */
public class BaseTest {

  @Before
  public void before(){
    LastControl.pullMatchers();
  }

  @After
  public void after(){
    LastControl.pullMatchers();
  }

}

Basicly let your test that fail with the Matchers error extend from this class and you'll be sure the Matchers are cleaned. Note this IS A WORKAROUND. The offending tests should have been written right in the first place. But if you have to wade through 5000+ tests , this is the lesser of two evils. I hope this will help people out !

Related Topic