Kyle
Kyle

Reputation: 14666

Mocking DataSource for JdbcTemplate with Mockito

I'm trying to test a class in a Spring project. I would like to make as many changes as possible in the test class vs. the dao class so that I don't have to retest all sorts things because of a change.

The class I'm working with has a JdbcTemplate template class variable that is instantiated by the following:

setJdbcTemplate(DataSource dataSource) {
    this.template = new JdbcTemplate(dataSource);
}

The method I would like to test makes a template.query(<code>) to run a defined SQL query and return the results to a list.

I created the following in my test case, but I'm not sure how to put it into use. Can I make the following code return a certain list of Strings using Mockito?

DataSource mockedDataSrc = Mockito.mock(DataSource.class);
customerClassDao.setJdbcTemplate(mockedDataSrc); 

Can I somehow use the when or another command to set what I want to be returned to the JdbcTemplate's .query call?

Upvotes: 4

Views: 47746

Answers (2)

duffymo
duffymo

Reputation: 308733

If you're testing a DAO it makes no sense at all to mock the data source. What are you testing? You need to make a DAO that interacts with the database.

Once you have that working, you're free to mock the interface-based DAO when testing services that use it. You've already tested the DAO; there's no reason to redo it when testing the services.

I'd say you're off-track if you're mocking the data source when testing the DAO.

Upvotes: 4

Daniel Kaplan
Daniel Kaplan

Reputation: 67300

You can't do this because you don't have control over the JdbcTemplate implementation. You should dependency inject the JdbcTemplate and then mock the JdbcTemplate instead.

This difficulty is pointing out a problem with your code. Your code depends on the concrete instance of JdbcTemplate. It would be less coupled if you used Dependency Injection on it instead.


Since you don't want to modify your system under test, you can do this:

Change the template field so it's package protected (ie: remove the private keyword). Then, I'd set it to be a mock(JdbcTemplate.class) after you instantiate the class you're testing. Now you'll be able to use when and verify on the JdbcTemplate directly like you wanted originally.

So the class you're testing will look like this:

public class SystemUnderTest {

JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(DataSource dataSource) {
        this.template = new JdbcTemplate(dataSource);
    }

}

And your test will do this:

@Before
public void setUp() {
    SystemUnderTest sut = new SystemUnderTest();
    sut.jdbcTemplate = mock(JdbcTemplate.class);                
}

// ...

Upvotes: 4

Related Questions