Reputation: 18639
I have the following structure:
public class MyDao{
private JdbcTemplate jdbcTemplate;
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public VCASDao(DataSource dataSource ){
jdbcTemplate = new JdbcTemplate(dataSource);
}
}
Some Manager class
public class MyManager{
MyDao dao = null;
private DataSource dataSource;
public MyManager(){}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void someMethod(Object o){
dao.save(o);
}
}
}
and facade class
public class MyFacadeClass{
private MyManager manager;
public MyFacadeClass(){
manager = new MyManager();
}
public void someFacadeMethod(Object o){
manager.someMethod(o);
}
}
Now I would like to test it with JUnit and Mockito. My problem is that I don't have JNDI schema and I need to mock JdbcTemplate with DataSource based on HSQLDB.
My mocking looks like this:
@Mock
static BasicDataSource dataSource ;
@Mock
static JdbcTemplate jdbcTemplate ;
@Mock
MyDao dao;
MyFacadeClass myFacadeClass = new MyFacadeClass();
@BeforeClass
public static void init(){
dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:mem:Test");
dataSource.setUsername("sa");
dataSource.setPassword("");
dataSource.setInitialSize(5);
dataSource.setMaxActive(10);
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxOpenPreparedStatements(10);
jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate
.execute("create Some Table");
}
@Test
public void testSomeFacadeMethod(){
Object o = new Object();
myFacadeClass.someFacadeMethod(o);
}
I'm getting exception in MyManager constructor that JNDI name for "some_DB" does not exist.
I think I have a problem with Mocking general approach. please help.
P.S: I'm not using spring in this project just use JdbcTemplate class for code simplicity.
Update:
I changed my classes but now dao object is null.
Upvotes: 2
Views: 1007
Reputation: 42223
From what you posted, I gather you want to test MyFacadeClass
. If that is indeed the case you are mocking the wrong stuff here.
The only interesting relationship is MyFacadeClass
-> MyManager
. JNDI and JdbcTemplate aren't even visible to MyFacadeClass
, why would you make them appear in your test ;)
Here's the direction I would go, while keeping the same architecture :
So in MyFacadeClassTest
you should only mock MyManager
and inject it in MyFacadeClass
, and test the relevant scenarios.
In MyManager
, I would advise you to not test JNDI stuff, for example you can create a package visible constructor that directly take a MyDao
object. It would be even better to externalize this JNDI stuff in another class, it could be something like MyDaoProvider
.
Then in MyManagerTest
you will test the relevant interaction between MyManager
and a MyDao
mock.
Finally, you'll want to test MyDao
, as the DAO can only be tested correctly with a real database, this means that it will need another system to run. This test is an integration test. You will either run it against the real DB (Oracle, etc.) or an in memory DB (HSQLDB,etc.), in this case you will create a real JdbcTemplate according to your test environment, and you will inject it in the DAO. Also you can not run these tests at all, you'll run business acceptance tests instead.
Hope that helps.
Upvotes: 5
Reputation: 47373
MyManager
shouldn't lookup the datasource. The datasource should be injected into it. This is the Dependency Injection
principle. It makes testing easier because you can easily put your own implementation into it(in this case your own datasource).
Another option is to add a getDataSource()
method into the MyManager
class and then mock it.
Upvotes: 1