У меня есть следующая задача, и я не нашел хорошего ответа. Я использую среду Mocking (в данном случае JMock), чтобы позволить модульным тестам быть изолированными от кода базы данных. Я издеваюсь над доступом к классам, которые включают логику базы данных, и отдельно тестирую классы базы данных с помощью DBUnit.
Проблема, с которой я сталкиваюсь, заключается в том, что я замечаю шаблон, в котором логика концептуально дублируется в нескольких местах. Например, мне нужно определить, что значение в базе данных не существует, поэтому в этом случае я могу вернуть null из метода. Итак, у меня есть класс доступа к базе данных, который взаимодействует с базой данных и возвращает значение null соответствующим образом. Затем у меня есть класс бизнес-логики, который получает null от макета, а затем проверяется на правильность действий, если значение равно null.
А что, если в будущем это поведение нужно будет изменить, а возврат null больше не будет уместным, скажем, из-за того, что состояние стало более сложным, поэтому мне нужно будет вернуть объект, который сообщает, что значение не существует, и какой-то дополнительный факт из базу данных.
Теперь, если я изменю поведение класса базы данных, чтобы в этом случае он больше не возвращал значение null, класс бизнес-логики по-прежнему будет функционировать, и ошибка будет обнаружена только в отделе контроля качества, если только кто-то не вспомнит связь или не следует правильно использования метода.
Мне показалось, что я что-то упускаю, и должен быть лучший способ избежать этого концептуального дублирования или, по крайней мере, протестировать его, чтобы, если оно изменится, тот факт, что изменение не распространяется, не прошел модульный тест.
Какие-либо предложения?
ОБНОВИТЬ:
Попробую уточнить свой вопрос. Я думаю о том, когда код будет развиваться с течением времени, как убедиться, что интеграция не прерывается между классами, протестированными с помощью макета, и фактической реализацией класса, который представляет макет.
Например, у меня только что был случай, когда у меня был метод, который был изначально создан и не ожидал нулевых значений, поэтому это не был тест на реальном объекте. Затем пользователь класса (протестированный с помощью макета) был расширен, чтобы передавать значение null в качестве параметра при определенных обстоятельствах. При интеграции, которая сломалась, потому что настоящий класс не был проверен на нуль. Теперь при создании этих классов сначала это не имеет большого значения, потому что вы тестируете оба конца по мере создания, но если дизайн должен развиваться два месяца спустя, когда вы склонны забывать о деталях, как вы будете тестировать взаимодействие между эти два набора объектов (тот, который тестировался с помощью макета по сравнению с фактической реализацией)?
Основная проблема, по-видимому, заключается в дублировании (то есть нарушении принципа DRY), ожидания действительно хранятся в двух местах, хотя связь концептуальна, фактического дублирующего кода нет.
[Редактировать после второго редактирования ответа Аарона Дигуллы]:
Правильно, именно этим я и занимаюсь (за исключением того, что есть некоторое дальнейшее взаимодействие с БД в классе, который тестируется через DBUnit и взаимодействует с базой данных во время ее тестов, но это та же идея). Итак, теперь предположим, что нам нужно изменить поведение базы данных, чтобы результаты были другими. Тест с использованием мока будет продолжать проходить, если 1) кто-то не вспомнит или 2) он не сломается при интеграции. Таким образом, возвращаемые значения хранимой процедуры (скажем) базы данных по существу дублируются в тестовых данных макета. Что меня беспокоит в дублировании, так это то, что дублируется логика, и это тонкое нарушение DRY. Может быть, это так и есть (в конце концов, есть причина для интеграционных тестов), но я чувствовал, что вместо этого я что-то упускаю.
[Редактировать при запуске награды]
Чтение взаимодействия с Аароном подходит к сути вопроса, но то, что я действительно ищу, - это некоторое понимание того, как избежать или управлять очевидным дублированием, чтобы изменение в поведении реального класса проявилось в модульные тесты, которые взаимодействуют с макетом как с чем-то, что сломалось. Очевидно, что это не происходит автоматически, но может быть способ правильно спроектировать сценарий.
[Редактировать присуждение награды]
Спасибо всем, кто потратил время, отвечая на вопрос. Победитель научил меня чему-то новому о том, как думать о передаче данных между двумя слоями, и первым нашел ответ.