Зачем мне использовать MockRunner вместо обычного / ручного внедрения зависимостей?
В нашей компании у нас есть сервисный уровень, который принимает некоторый XML-запрос, обращается к различным хранимым процедурам (SP) через JDBC, обрабатывает данные и отвечает некоторым ответным XML. В последнее время люди начали использовать MockRunner в своих тестах JUnit, чтобы высмеивать ответы от SP. Код для настройки ложных ответов от SP, использующих MockRunner, выглядит ужасно (это первый случайный тестовый класс, который я открыл):
MockConnection connection = new MockConnection();
MockContextFactory.setAsInitial();
InitialContext context = new InitialContext();
context.rebind(READ_PAYMENT_DATA_SOURCE, getDS());
getDS().setupConnection(connection);
m_csStatementHandler = connection.getCallableStatementResultSetHandler();
m_csStatementHandler.clearResultSets();
m_csStatementHandler.clearCallableStatements();
m_csStatementHandler.setExactMatch(false);
m_csStatementHandler.prepareReturnsResultSet(READ_PAYMENT, true);
m_csStatementHandler.setExactMatch(false);
m_csStatementHandler.setExactMatchParameter(false);
Map parameterMap = new HashMap();
parameterMap.put(new Integer(1), null);
parameterMap.put(new Integer(2), null);
parameterMap.put(new Integer(3), null);
parameterMap.put(new Integer(4), null);
m_csStatementHandler.prepareOutParameter(READ_PAYMENT, parameterMap);
//Set up the cursor of applications for return.
MockResultSet resultApps = m_csStatementHandler.createResultSet();
resultApps.addRow(getPaymentSchedule("E", "Monthly", new Short("1"),null,null,null,null,null,null,null));
resultApps.addRow(getPaymentSchedule("A", "Weekly", new Short("1"),null,null,null,null,null,null,null));
resultApps.addRow(getPaymentSchedule("R", "Yearly", new Short("1"),null,null,null,null,null,null,null));
resultApps.addRow(getPaymentSchedule("S", "Weekly", new Short("1"),null,null,null,null,null,null,null));
resultApps.addRow(getPaymentSchedule("W", "Monthly", new Short("1"),null,null,null,null,null,null,null));
MockResultSet[] results = new MockResultSet[1];
results[0] = resultApps;
m_csStatementHandler.prepareResultSet(READ_PAYMENT, resultApps);
Приведенный выше код ужасен по многим причинам, но он явно показывает сложность и издержки при настройке ответа от хранимых процедур.
До настоящего времени я использовал инъекцию зависимостей вручную, чтобы внедрить класс, который на самом деле вызывает хранимую процедуру. Все, что мне нужно сделать, это создать фиктивный класс вызывающего SP (ответственный за фактическое выполнение SP) и установить желаемые данные ответа. Я очень доволен этой техникой, и она намного проще, чем описанная выше, поскольку она ориентирована на данные, а не беспокоится о деталях реализации. Но мой вопрос: когда вы захотите использовать MockRunner? Это кажется излишним для модульных тестов, так что я предполагаю, что это больше для интеграции или тестирования системы? И даже тогда мне все еще кажется, что проще использовать инфраструктуру DI для замены класса вызывающего SP, а затем настраивать весь приведенный выше код для каждого вызова хранимой процедуры. Пожалуйста, просветите! Спасибо
1 ответ
В конечном итоге вы изучаете философию насмешек в целом. Я дам вам два моих цента, но я бы также сослался на любую серьезную насмешливую библиотеку, которая, вероятно, послужит хорошим оправданием для их собственного существования. Взять, к примеру, Мокито.
Сообщество по тестированию / макетированию часто различает то, что вы катите вручную, что обычно называется "заглушкой" (статический рукописный класс), и "макет" (динамический класс, генерируемый во время выполнения).
Преимущества насмешек довольно велики по сравнению с простой заглушкой. Многие тестировщики недовольны идеей переписать реализации интерфейсов и / или конкретных классов подклассов только для целей тестирования. Для этого часто требуется реализация ВСЕХ методов указанного класса / интерфейса, даже если вы просто хотите протестировать определенный метод.
Насмешка позволяет обойти эту проблему, определяя только методы, которым вы хотите дать поведение, и это мощно. Кроме того, издевательство позволяет менять поведение от одного теста к другому. Для этого нужно написать совершенно новый класс-заглушку.
Синтаксис немного варьируется от насмешливой библиотеки к библиотеке. Некоторые вы можете найти более читабельными, чем другие. Мой нынешний фаворит - Mockito, отсюда и более ранние ссылки, но они развиваются со временем. Может быть, стоит определить, почему ваша организация использует набор инструментов для имитации, и может ли другая по-прежнему удовлетворить ваши потребности и быть более читабельной.
Надеемся, что ваши тестеры пишут обычное поведение в методы настройки тестов (например, JUnit's @Before), поэтому вам не нужно постоянно видеть создание макетов и общую инициализацию повсюду.