Apr

13

I like the Spring Framework for Java development. It let’s me do all kinds of neat things like interceptors, but fundamentally, at it’s core it lets me break stuff apart to test it in chunks, while still having support for wiring it together to build a complete application.

Spring is all about dependency injection, so you’d think this sort of thing would be easy, and by and large, it is, but every now and again, I run into something that makes me think that someone’s not taking their own advice.  The latest was an excursion into EasyMock and the Spring JDBC transaction support classes. For reasons I won’t go in to, we’re using JdbcTemplate and not something newer like JPA or Hibernate.  In one of my DAO classes, I need to coordinate two deletes, and so I do this:

protected void startTransaction() {

 DefaultTransactionDefinition def = new DefaultTransactionDefinition();

 status = txManager.getTransaction(def);

}

and then carry on about my business. Now, when I want to mock that, first off I need to get a TransactionManager. Well, that’s a class, not an interface, so I have to use EasyMock’s class extension package. Ok, so now I need CG libraries to code engineer a new class extending AbstractTransactionManager:

   DataSourceTransactionManager mockTxManager =org.easymock.classextension.EasyMock.createMock(DataSourceTransactionManager.class);
  
    TransactionStatus status = EasyMock.createMock(TransactionStatus.class);
    replay(status);
    EasyMock.expect(mockTxManager.getTransaction(isA(TransactionDefinition.class)).andReturn(status);
    mockTxManager.commit(status);
    replay (mockTxManager);

Okay, now I should be good to go. It’s a bit irritating that I’ve got to use cglib to get the mock, but easy enough. Wait a second, what’s this?

java.lang.IllegalStateException: 0 matchers expected, 1 recorded.
        at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:56)

Well, it turns out after some poking around, and pulling of hair, I discovered that not only is AbstractTransactionManager a class, requiring me to “program to the class, not the interface” but getTransaction is final, so the cglib override didn’t stick.

Shame on EasyMock and cglib for not telling me my generated class wasn’t going to work, but this isn’t the first time I’ve run into behavior in the Spring Framework itself that makes me think they’re not taking their own medicine, and making it easy for me to inject what I need.

Blogroll

WP Themes