Replacing DataSource in Mockito

10,387

Solution 1

Since you're using @Mock, there is no need to actually instantiate those objects by calling their constructors.

Instead of:

@Mock
BasicDataSource dataSource = new BasicDataSource();

@Mock 
JNDIBasedDao dao = new JNDIBasedDao();

try:

@Mock
BasicDataSource dataSource;

@Mock 
JNDIBasedDao dao;

and let Mockito handle creating mock versions of those classes.

Of course, when you do this you get Mock versions of these classes, so calling all those methods on your dataSource would result in calls to default Mockito stubbings...which do nothing.

Not sure why you've combined @Mock with method calls on the same object which it looks like you expect to have a result...

Maybe step through the debugger and check the runtime class of the objects youre using at the point the exception is thrown. They might not be what you expect them to be.

Solution 2

@InjectMocks will do only setter injection.

Change the following in Manager class

private JNDIBasedDao dao = new JNDIBasedDao();

to

private JNDIBasedDao dao;

and add

void setDao(JNDOBasedDao dao)
{
   this.dao = dao;
}

Solution 3

You could create a second constructor and inject the InitialContext.

public class JNDIBasedDao {
  DataSource dataSource;

  public JNDIBasedDao() {
    this(new InitialContext());
  }

  public JNDIBasedDao(InitialContext ic) {
    try {
      dataSource = (DataSource) ic.lookup("java://bla-bla-bla");
    } catch (NamingException e) {
      e.printStackTrace();
    }
  }

  ....
}

Now you're able to provide a mocked InitialContext, which provides your DataSource.

Share:
10,387
danny.lesnik
Author by

danny.lesnik

Java Expert at Tikal Knowledge. Interesting in Spring/Hibernate/NoSQL/Spring MVC and other Java top edge technology. Twitter LinkedIn Facebook

Updated on June 04, 2022

Comments

  • danny.lesnik
    danny.lesnik almost 2 years

    I have code which performs query on Jboss server. It has JNDI based datasource and looks like this:

        public class JNDIBasedDao {
    
            DataSource dataSource;
    
            public JNDIBasedDao(){
    
                try {
                    InitialContext ic = new InitialContext();
                    dataSource = (DataSource) ic.lookup("java://bla-bla-bla");
                } catch (NamingException e) {
                e.printStackTrace();
                }
    
    
            }
    
    public class Manager {
    
        public Manager(){}
    
        private JNDIBasedDao dao = new JNDIBasedDao();
    
        public void runOperation(){
            this.dao.executeInsert();
        }
    

    On my laptop I have no Jboss and no ability to connect to this server and want to run Unit testing on HSQLDB.

    I want to create BasicDataSource from apache commons based on HSQLDB and inject this object into JNDIBasedDao.

    @Mock
    BasicDataSource dataSource = new BasicDataSource();
    
    @Mock 
    JNDIBasedDao dao = new JNDIBasedDao();
    
    @InjectMocks
    Manager manager = new Manager();
    @Before
        public void initMocks(){
            dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
            dataSource.setUrl("jdbc:hsqldb:mem:dannyTest");
            dataSource.setUsername("sa");
            dataSource.setPassword("");
            dataSource.setInitialSize(5);
            dataSource.setMaxActive(10);
            dataSource.setPoolPreparedStatements(true);
            dataSource.setMaxOpenPreparedStatements(10);
    
            MockitoAnnotations.initMocks(this);
    
        }
    
        @Test
        public void testRunOperartion() {
            manager.runOperartion();
        }
    

    but I'm still getting JNDI error. Can it be done? Please help.

  • Tom Tresansky
    Tom Tresansky about 12 years
    In the latest version, @InjectMocks does field injection also. See: docs.mockito.googlecode.com/hg/latest/org/mockito/…