increasing code coverage for JdbcTemplate mocking

16,593

Solution 1

One way of doing this is as follows:

final List<String> resultList = new ArrayList<String>();
resultList.add("test1");
resultList.add("test2");

final JdbcTemplate template = mock(JdbcTemplate.class);

when(template.query(anyString(), any(Object[].class), any(RowMapper.class)))
    .thenAnswer(new Answer<List<String>>() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            // Fetch the method arguments
            Object[] args = invocation.getArguments();

            // Fetch the row mapper instance from the arguments
            RowMapper<String> rm = (RowMapper<String>) args[2]; 

            // Create a mock result set and setup an expectation on it
            ResultSet rs = mock(ResultSet.class);
            String expected = "value returned by query";
            when(rs.getString(1)).thenReturn(expected);

            // Invoke the row mapper
            String actual = rm.mapRow(rs, 0);

            // Assert the result of the row mapper execution
            assertEquals(expected, actual);

            // Return your created list for the template#query call
            return resultList;
        }
    });

But as you can see, it's a lot of code to test the row mapper :)

Personally, I would prefer going with an integration test OR moving the row mapper to a class of its own and unit testing it separately.

Solution 2

you are mocking jdbcTemplate so your production jdbcTemplate have no chance of being executed and fire the rowMapper. if you really want to mock it then you have to mock query in a way it still fires the rowMapper and passes to it fake ResultSet. you can also extract the rowMapper and test it individually. but it makes you spend more time on writing tests and get nothing in return. don't do it. db code should be tested during integration tests with an actual database.

Share:
16,593
NamingException
Author by

NamingException

Working as Lead Software Engineer in J2EE Technologies

Updated on June 05, 2022

Comments

  • NamingException
    NamingException almost 2 years

    I am mocking JdbcTemplate for unit test cases, as don't want to hit actual database integration.

    But it is decreasing my code coverage (Red indicates missing coverage).

    enter image description here

    Below is the snippet used. Same case happens by using user defined mappers.

    final List<String> resultList = new ArrayList<String>();
    resultList.add("test1");
    resultList.add("test2");
    final JdbcTemplate template = Mockito.mock(JdbcTemplate.class);
    Mockito.when(
        template.query(Mockito.anyString(), Mockito.any(Object[].class),
            Mockito.any(RowMapper.class))).thenReturn(resultList);
    sampleDao.setJdbcTemplate(template);
    

    Any ideas for increasing code coverage in dao class. All methods doesn't suit for user defined row mappers in my case.