Unit testing a java class extending Stored Procedure with EasyMock

ShilR picture ShilR · Apr 4, 2013 · Viewed 7.9k times · Source

When I try to unit test the following class extending StoredProcedure I am getting an NullPointerException at the line: return (Map) execute(csc, new CallableStatementCallback() in JDBCTemplate class. I mocked the bean that is being passed in execute method, DataSource, and the sql.

public class MyStoredProc extends StoredProcedure {
    /**
     * Constructor - sets SQLParameters for the stored procedure.
     * 
     * @param ds - DataSource
     */
    public MyStoredProc(DataSource dataSource, String sql) {
        super(dataSource, sql);
        declareParameter(new SqlOutParameter("return",Types.NUMERIC));
        declareParameter(new SqlParameter("BATCH_ID",Types.NUMERIC));
        declareParameter(new SqlParameter("PROCESS_TYPE",Types.VARCHAR));

        complie(); 
    }

    public BigDecimal execute(MyBean bean){
        BigDecimal returnValue = BigDecimal.valueOf(-1);

        Map in = new HashMap();

        in.put("BATCH_ID", bean.getBatchID());
        in.put("PROCESS_TYPE", bean.getProcessType());

        Object obj = execute(in);
        if (obj != null) {
            Object output = ((HashMap) obj).get("return"); 

            if( output instanceof BigDecimal) {
                returnValue = (BigDecimal)output;
            }
        }
        return bigDec; 
    }
}

test case: P.S - When I debug this test case, StoredProcedure mock is not being used at all.Instead the actual implementation is used.

public class MyStoredProcTest {
private MyStoredProc mysp;
private DataSource dataSource;
private String sql;
@Before
public void setUp() {
    dataSource = EasyMock.createMock(DataSource.class);
    sql = "Testing";
    mysp = new MyStoredProc(dataSource, sql);
}

@Test
public void testExecute() {

    StoredProcedure storedProcedure = EasyMock
            .createMock(StoredProcedure.class);
    HashMap map = new HashMap();
    map.put("return", BigDecimal.ONE);
    expect(storedProcedure.execute(EasyMock.anyObject(Map.class))).andReturn(map);

    Connection con = EasyMock.createMock(Connection.class);
    expect(dataSource.getConnection()).andReturn(con);   
    MyBean bean = EasyMock.createMock(MyBean.class);


    expect(bean.getBatchID()).andReturn(BigDecimal.valueOf(.0001))
            .anyTimes();
    expect(bean.getProcessType()).andReturn("Process Type").anyTimes();

    replay(bean, dataSource, storedProcedure, con);
    BigDecimal returnValue = null;
    try {
        returnValue = mysp.execute(bean);
    } catch (Exception e) {
        System.out.println("exception" + e.getStackTrace());//  the Null pointer from JDBCTemplate is caught here.
    }
    Assert.assertEquals(BigDecimal.valueOf(-1), returnValue);
}

Answer

user138439 picture user138439 · Apr 5, 2013

Some of your mocks are not being used because you are not replaying them. You should modify replay(bean) to replay(bean, datasource, storedProcedure)

On another note, map does not need to be mocked. When you expect the call to storedProcedure.execute(...) you can return the pre-populated map.