Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I unit test a class that uses SimpleJdbcCall

I have a class that looks like this:

public class MyClass {

    private final SimpleJdbcCall simpleJdbcCall;

    public MyClass(final DataSource dataSource) {
        this(new JdbcTemplate(dataSource));
    }

    public MyClass(final JdbcTemplate template) {
        simpleJdbcCall = new SimpleJdbcCall(template)
            .withoutProcedureColumnMetaDataAccess()
            .withCatalogName("MY_ORACLE_PACKAGE")
            .withFunctionName("GET_VALUE")
            .withReturnValue()
            .declareParameters(
                new SqlOutParameter("RESULT", Types.VARCHAR))
            .declareParameters(
                new SqlParameter("P_VAR1_NAME", Types.VARCHAR))
            .declareParameters(
                new SqlParameter("P_VAR2_NAME", Types.VARCHAR))
            .useInParameterNames("P_VAR1_NAME", "P_VAR2_NAME");
    }

    private String getValue(final String input) {
        final SqlParameterSource params = new MapSqlParameterSource()
            .addValue("P_VAR1_NAME", input, Types.VARCHAR)
            .addValue("P_VAR2_NAME", null, Types.VARCHAR);
        return simpleJdbcCall.executeFunction(String.class, params);
    }
}

It works as expected, but I want to write a unit test for it and it's driving me crazy. I've tried mocking the JdbcTemplate (Mockito), but that leads to mocking connections, metadata, etc, and I get lost about the time callable statement factories come into play.

I guess I could write it so that the SimpleJdbcCall is passed as a parameter to a new constructor and then mock that, but that feels hackish. I'd prefer the test not affect the class unless it's to improve it.

I'd like to keep using this SimpleJdbcCall API. It writes the SQL for me so I don't have to mix SQL and Java, but I would also really like to test this thing without having to write 1000 lines of code. Can anyone see a good way to test this?

like image 666
Matt Malone Avatar asked Sep 26 '22 10:09

Matt Malone


1 Answers

I too prefer not to inject 15 different SimpleJdbcCalls into my repository, so I bite the bullet and add this to my test setup method:

DatabaseMetaData metaData = mock(DatabaseMetaData.class);
Connection con = mock(Connection.class);
when(con.getMetaData()).thenReturn(metaData);
DataSource ds = mock(DataSource.class);
when(ds.getConnection()).thenReturn(con);
jdbcTemplate = mock(JdbcTemplate.class);
when(jdbcTemplate.getDataSource()).thenReturn(ds);
like image 90
Jeff E Avatar answered Sep 29 '22 06:09

Jeff E