Имитация источника данных для JdbcTemplate с помощью Mockito

Я пытаюсь протестировать класс в проекте Spring. Я хотел бы внести как можно больше изменений в тестовый класс по сравнению с классом dao, чтобы мне не приходилось повторно тестировать всевозможные вещи из-за изменения.

Класс, с которым я работаю, имеет переменную класса JdbcTemplate template, экземпляр которой создается следующим образом:

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

Метод, который я хотел бы протестировать, заставляет template.query(<code>) запускать определенный SQL-запрос и возвращать результаты в список.

Я создал следующее в своем тестовом примере, но я не уверен, как его использовать. Могу ли я заставить следующий код возвращать определенный список строк, используя Mockito?

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

Могу ли я каким-то образом использовать when или другую команду, чтобы установить, что я хочу вернуть в вызов .query JdbcTemplate?


person Kyle    schedule 27.03.2013    source источник


Ответы (2)


Вы не можете этого сделать, потому что у вас нет контроля над реализацией JdbcTemplate. Вы должны ввести зависимость JdbcTemplate, а затем вместо этого издеваться над JdbcTemplate.

Эта трудность указывает на проблему с вашим кодом. Ваш код зависит от конкретного экземпляра JdbcTemplate. Это было бы менее связано, если бы вместо этого вы использовали Injection Dependency Injection.


Поскольку вы не хотите изменять тестируемую систему, вы можете сделать это:

Измените поле template, чтобы оно было защищено пакетом (т.е. удалите ключевое слово private). Затем я бы установил его как макет (JdbcTemplate.class) после того, как вы создадите экземпляр класса, который вы тестируете. Теперь вы сможете использовать when и проверять JdbcTemplate напрямую, как вы хотели изначально.

Таким образом, класс, который вы тестируете, будет выглядеть так:

public class SystemUnderTest {

JdbcTemplate jdbcTemplate;

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

}

И ваш тест сделает это:

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

// ...
person Daniel Kaplan    schedule 27.03.2013
comment
Источник данных вводится через Spring через applicationContext.xml. Я не уверен, почему они решили просто внедрить источник данных вместо jdbcTemplate, но я пытался проверить свой метод, который я написал, без необходимости изменять/рефакторить слишком много остального кода. Поскольку мое изменение действительно влияет только на 1 вызов SQL в 1 методе. - person Kyle; 28.03.2013
comment
Ваш тест рухнет, если вы имитируете источник данных и передаете его прямо сейчас? Если нет, вы можете кое-что сделать, но сначала мне нужно это узнать. - person Daniel Kaplan; 28.03.2013
comment
Не вылетает, просто пишет успешно. Я просто не знал, куда идти отсюда, я очень новичок в Mockito/jUnit. Я гуглил несколько часов и до сих пор не понял, куда идти, кроме двух строк, которые я показал выше. - person Kyle; 28.03.2013
comment
Спасибо, это направило меня в правильном направлении. Очень ценю. - person Kyle; 28.03.2013

Если вы тестируете DAO, нет смысла издеваться над источником данных. Что вы тестируете? Вам нужно сделать DAO, который взаимодействует с базой данных.

После того, как у вас это заработает, вы можете свободно имитировать DAO на основе интерфейса при тестировании сервисов, которые его используют. Вы уже протестировали DAO; нет причин переделывать это при тестировании сервисов.

Я бы сказал, что вы сбились с пути, если вы издеваетесь над источником данных при тестировании DAO.

person duffymo    schedule 27.03.2013
comment
Может быть полезно протестировать RowMapper или какой-либо другой код в DAO, который берет набор результатов и создает что-то, отличное от стандартного ответа на запрос. - person DomenicDatti; 08.08.2016
comment
Если DAO работает, вы можете либо смоделировать ResultSet, либо включить RowMapper в тесты DAO. - person duffymo; 08.08.2016