Замена источника данных в Mockito - PullRequest
2 голосов
/ 15 марта 2012

У меня есть код, который выполняет запрос на сервере Jboss. Он имеет источник данных на основе JNDI и выглядит следующим образом:

    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();
    }

На моем ноутбуке нет Jboss и нет возможности подключиться к этому серверу, и я хочу запустить модульное тестирование на HSQLDB.

Я хочу создать BasicDataSource из Apache Commons на основе HSQLDB и внедрить этот объект в 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();
    }

но я все еще получаю ошибку JNDI. Это можно сделать? Пожалуйста, помогите.

Ответы [ 3 ]

1 голос
/ 15 марта 2012

Вы можете создать второй конструктор и внедрить 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();
    }
  }

  ....
}

Теперь вы можете предоставить имитированный InitialContext, который предоставляет ваш DataSource.

1 голос
/ 16 марта 2012

Так как вы используете @Mock, нет необходимости фактически создавать экземпляры этих объектов, вызывая их конструкторы.

Вместо:

@Mock
BasicDataSource dataSource = new BasicDataSource();

@Mock 
JNDIBasedDao dao = new JNDIBasedDao();

try:

@Mock
BasicDataSource dataSource;

@Mock 
JNDIBasedDao dao;

и пусть Mockito обрабатывает создание фиктивных версий этих классов.

Конечно, когда вы делаете это, вы получаете Mock версии этих классов, поэтому вызываете все эти методы на вашемdataSource приведет к вызовам по умолчанию для заглушек Mockito ... которые ничего не делают.

Не уверен, почему вы объединили @Mock с вызовами методов для того же объекта, который, как вы думаете, будет иметь результат...

Возможно, пройдитесь по отладчику и проверьте класс времени выполнения объектов, которые вы используете в момент, когда выдается исключение.Они могут быть не такими, как вы ожидаете.

1 голос
/ 15 марта 2012

@ InjectMocks будет выполнять только инъекцию сеттера.

Измените следующее в классе менеджера

private JNDIBasedDao dao = new JNDIBasedDao();

на

private JNDIBasedDao dao;

и добавьте

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