When using MyBatis SQL Maps as your ORM framework, its very common to need to implement a type handler for any custom types/enums you want to persist.
These implementations can all look very similar and usually behave in a similar fashion and so it is an easy target for automating the unit testing to avoid confusion and mistakes though cut and paste*.
The Testing Class
package com.macbtech.blog.testing; import java.sql.SQLException; import org.easymock.EasyMock; import org.easymock.IMocksControl; import org.junit.Assert; import com.ibatis.sqlmap.client.extensions.ParameterSetter; import com.ibatis.sqlmap.client.extensions.ResultGetter; import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback; public class SQLMapTypeHandlerTester<T> { final private IMocksControl mockControl = EasyMock.createControl(); public void testHandler(final TypeHandlerCallback handler, final T[] types, final int nullType) throws SQLException { testGetResults(handler, types); testSetParameter(handler, types, nullType); testSetValueOf(handler, types); } @SuppressWarnings("unchecked") private void testGetResults(final TypeHandlerCallback handler, final T[] types) throws SQLException { final ResultGetter resultGetterMock = mockControl.createMock(ResultGetter.class); EasyMock.expect(resultGetterMock.getString()).andReturn(null); for (final T type : types) { EasyMock.expect(resultGetterMock.getString()).andReturn(type.toString()); } mockControl.replay(); Assert.assertNull("Expected null",handler.getResult(resultGetterMock)); for (final T type : types) { Assert.assertEquals("Unexpected result", type, (T)handler.getResult(resultGetterMock)); } mockControl.verify(); mockControl.reset(); } private void testSetParameter(final TypeHandlerCallback handler, final T[] types, final int nullType) throws SQLException { final ParameterSetter parameterSetterMock = mockControl.createMock(ParameterSetter.class); parameterSetterMock.setNull(nullType); for (final T type : types) { parameterSetterMock.setString(type.toString()); } mockControl.replay(); handler.setParameter(parameterSetterMock, null); for (final T type : types) { handler.setParameter(parameterSetterMock, type); } mockControl.verify(); mockControl.reset(); } private void testSetValueOf(final TypeHandlerCallback handler, final T[] types) throws SQLException{ Assert.assertEquals("Unexpected value of", null, handler.valueOf(null)); for (final T type : types) { Assert.assertEquals("Unexpected value of", type, handler.valueOf(type.toString())); } } }
The Unit Test
@Test public void testCustomTypeTypeHandler() throws SQLException { SQLMapTypeHandlerTester<CustomType> customTypeTester = new SQLMapTypeHandlerTester<CustomType>(); customTypeTester.testHandler(new CustomTypeTypeHandler(), CustomType.values(), Types.VARCHAR); }
* this has killed me too many times!