Friday, September 24, 2010

UnitTesting - Mocking for MyBatis

Since I've recently dived into developing with MyBatis, I also started doing unit-test for my library.

I was ignored by two facts

  1. The test ran really slow. Like 1 sec pr. test
  2. My data changed during the day - testing in a shared test-environment
So I sat down and read some of the MyBatis source code for the classes I use. And found out I just needed to create two Mock classes and I would be good. So I did, following is the code, some of the methods for implementation was removed since they only throw a "UnsupportedOperationException":


MockSqlSession

package com.zylinc.zydata.mybatis.mocking;

import org.apache.ibatis.session.SqlSession;

/**
 *
 * @author Nicolai Willems
 */
class MockSqlSession implements SqlSession {

    public void close() {
        // Do nothing
        // Maybee destruct object
        // Naah who cares??
    }

    public  T getMapper(Class type) {
        String mockClass, interfaceName, packageName, mockClassName;
        Class typeToInstantiate;
        T result = null;

        interfaceName = type.getName();
        int lastIndex = interfaceName.lastIndexOf('.')+1; // Plus one to get of the '.' again
        packageName = interfaceName.substring(0, lastIndex);
        mockClassName = interfaceName.substring(lastIndex);

        if(mockClassName.startsWith("I")){
            mockClassName = mockClassName.substring(1);
        }

        mockClassName = "Mock"+mockClassName;

        mockClass = packageName+mockClassName;
        try{
            typeToInstantiate = Class.forName(mockClass);
            result = (T)typeToInstantiate.newInstance();
        }catch(ClassNotFoundException e){
            System.out.println("Class not found: "+e.getMessage());
            System.out.println("Cause was: "+e.getCause().toString());
            e.printStackTrace(System.out);
        }catch(InstantiationException e){
            System.out.println("Class instantiation failed: "+e.getMessage());
            System.out.println("Cause was: "+e.getCause().toString());
            e.printStackTrace(System.out);
        }catch(IllegalAccessException e){
            System.out.println("Illegal Access exception: "+e.getMessage());
            System.out.println("Cause was: "+e.getCause().toString());
            e.printStackTrace(System.out);
        }
        return result;
    }
}


MockSqlSessionFactory

For readability I have removed all of the other openSession-methods, since they just do "return this.openSession();"
package com.zylinc.zydata.mybatis.mocking;

import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

/**
 *
 * @author Nicolai Willems
 */
public class MockSqlSessionFactory implements SqlSessionFactory {

    private Configuration configuration;

    public SqlSession openSession() {
        return new MockSqlSession();
    }

    public Configuration getConfiguration() {
        return this.configuration;
        //throw new UnsupportedOperationException("Not supported yet.");
    }

}

If you have any questions felle free to contact me, either in the comments field or on the MyBatis user list.

1 comment:

Anonymous said...

You need to look into JMock - no need to write "real" Mock objects

Choose a month: