Testing MyBatis Type Handlers

Testing MyBatis Type Handlers
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!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.