Search code examples
javaunit-testingjunitmockitojdbctemplate

How to mock BeanPropertyRowMapper in Junit (Springboot)?


I'm writing a test case for Email DAO layer. which is something like:

@Repository
@PropertySource({ "classpath:/query.properties" })
public class DaoLayerImpl implements DaoLayerDao {

    /** The jdbc template. */
    @Qualifier("mariaJdbcTemplate")
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /** The find staged query. */
    @Value("${someQuery}")
    String someQuery;

    @Override
    public List<SomeBean> getData() throws MariaDbException {

        List<SomeBean> listOfData = new ArrayList<>();
        try {
            listOfData = jdbcTemplate.query(someQuery,
                    new BeanPropertyRowMapper<SomeBean>(SomeBean.class));
        } catch (RuntimeException e) {
            logger.error("RuntimeException in ", e);
        }

        return listOfData;
    }
}

The Test case for this layer is :

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@PropertySource("classpath:application-test.properties")
public class EmailDaoLayerTest {

    @MockBean
    JdbcTemplate jdbcTemplate;

    @InjectMocks
    DaoLayerImpl dao;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        jdbcTemplate = Mockito.mock(JdbcTemplate.someQuery);
        ReflectionTestUtils.setField(dao, "jdbcTemplate", jdbcTemplate);

    }

    @Test
    public void testCaseForGetData() throws Exception {
        List<SomeBean> beanObject = new ArrayList<>();
        beanObject.add(new SomeBean());
        beanObject.add(new SomeBean());
        beanObject.add(new SomeBean());

        System.out.println(beanObject.size()); // 3

        when(jdbcTemplate.query("someQuery",
                new BeanPropertyRowMapper<SomeBean>(SomeBean.class))).thenReturn(beanObject);


        List<SomeBean> obj = dao.getData();

        System.out.println(obj.size()); //0

        System.out.println("Done");

    }

}

After mocking the object size comes out to be 0 instead of 3. The size of the object before returning is 3. when i actually hitted the DAO, the size of the object comes out to be 0, whereas i had already mocked the jdbc template using when-then .

What is the correct way to mock Bean Property Row Mapper class?


Solution

  • Let me answer the question and then criticize your approach, maybe it will help to better understand how the solution should look like at the end.

    So to answer your question:

    Technically you can probably do something like:

    import static org.mockito.ArgumentMatchers.eq;
    import static org.mockito.ArgumentMatchers.any;
    ...
    Mockito.when(jdbcTemplate.query(eq("someQuery"), 
    any(BeanPropertyRowMapper.class)).thenReturn(....);
    
    

    However, you should ask yourself what exactly are you trying to test here? You have a relatively expensive integration test here that runs the Spring Context (it works with SpringRunner) and creates many objects under the hood.

    However based on the method to be tested - I don't see that there is any "meaningful" (subject to tests) code to be tested. You could test that given the query, the BeanPropertyRowMapper indeed can convert the response to instances of SomeBean but then again you mock it and it doesn't really run.

    You could check that the query you've prepared runs against the Database and returns the expected results, but it doesn't seem that you prepare any database here.

    So If the purpose is coverage - then yes you will be covered, but the tests are not about the coverage, but about making you "sure" that your code works properly. In this case, running the Spring Driven integration Test (with application context and everything) seems to be a huge overkill, MockitoRunner could do the job