Как избежать возвращения издевательств из списка изделенного объекта
Я пытаюсь разработать дизайн/дизайн. Кажется, у меня проблемы с тем, чтобы избежать издевательств из mocks в случае объектов, которым нужна служба для извлечения других объектов.
Примером может быть объект, который проверяет, оплачиваются ли счета за последний месяц. Ему нужна служба, которая извлекает список счетов. Поэтому мне нужно высмеять этот billRetrievalService в моих тестах. В то же время мне нужно, чтобы BillRetrievalMock возвращал издевавшиеся счета (так как я не хочу, чтобы мой тест полагался на правильность реализации Билла).
Является ли мой дизайн ошибочным? Есть ли лучший способ проверить это? Или это так, как это должно быть при использовании объектов искателя (обнаружение счетов в этом случае)?
side note: althout Bill может быть кандидатом на объект значения, более широкая проблема по-прежнему сохраняется, когда коллекции не содержат объекты значений (например, пользователи).
Ответы
Ответ 1
В большинстве случаев, если мне нужен макет, чтобы вернуть еще один макет, я нахожу зависимость, которая имеет больше смысла в другом направлении. Иными словами, макет-возврат-макет обычно указывает на нарушение принципа инверсии зависимостей.
Одно общее исключение: a factory, который создает объекты (в отличие от "держателя", который каждый раз возвращает один и тот же объект). Если мне нужно создать несколько объектов одного типа во время моей жизни, мне может потребоваться зависеть от ObjectFactory
и вызвать #createObject()
, а затем, возможно, установить ожидания для объектов. Тем не менее, я бы поставил под сомнение это. Возможно, что-то еще один уровень вверх по стеку вызовов, чтобы создать Object
для меня и предоставить их мне по мере необходимости.
В случае ObjectHolder
, а не в зависимости от ObjectHolder
, чтобы получить Object
, я предпочитаю напрямую зависеть от Object
и заставляю моего вызывающего абонента передать его мне, но он хочет. Это соответствует желаемому конструктивному свойству независимости контекста.
Одной конкретной версией этой проблемы является шаблон "Виртуальные часы". Иногда вам нужно зависеть от виртуальных часов, но часто лучше просто требовать отметки времени. (Шаблон "Мгновенный запрос".)
Ответ 2
Mock return mocks - сильный запах кода - возможная проблема с дизайном. Возможно, что векселя должны быть неизменяемыми объектами ценностей, которые не следует издеваться. Или существует некоторая путаница с дизайном и обязанностями классов.
Книга Растущее объектно-ориентированное программное обеспечение, руководствуясь тестами и документ Макет ролей, а не объектов от изобретателей макетных объектов стоит прочитать.
Ответ 3
Обычно, когда я издеваюсь, я получаю триаду объектов. Первым объектом будет координатор BillsPaidLastMonthCoordinator
, этот объект имеет две зависимости BillRetrievalService
и BillPaidValidator
.
Вы бы издевались над двумя зависимостями, и ваш тест будет связан с взаимодействием извлечения и передачи счетов на проверку. Поэтому для этого теста вам все равно, что данные. Это помогает разделить обязанности. Ваш исходный объект отвечал за извлечение Bills
, а затем посмотрел, был ли он ispaid Bill.
С тем, как вы описали проблему, вы можете закончить, это шумный и хрупкий тест. Хрупкость исходит из того, что она может быть разбита двумя способами.
При использовании корридана он не должен меняться при изменении реализации Bill
. Просто объекты, которые на самом деле используют Bill
. Мои 2centavos.
[EDIT]
Это больше похоже на использование обработчиков событий (координатор)
Ответ 4
Как советуют Way of the Testuvius, ни один принцип, какой бы хорошей он ни был, должен быть принят абсолютно, и поэтому также с правилом вы не должны нуждаться в издевательстве, возвращающем макеты, бывают случаи, когда это вполне подходит.
Как предлагает Gutzofter, вы можете разбить свой объект на два, один для фактической проверки и еще один для поиска счетов для проверки. Преимущество этого принципа "единственной ответственности только" заключается в том, что валидатор будет более общим и многоразовым. С другой стороны, если у вас есть только этот простой вариант использования и нет особой необходимости в более высоком повторном использовании, очень прагматично сохранить поиск и проверку в одном классе. Слоение, взрыв количества предметов и т.д., Необоснованный реальной потребностью и реальной выгодой, выполненной только ради удовлетворения абстрактного принципа, не является хорошим. Вам всегда нужно взвешивать плюсы и минусы, и реальность редко бывает простой и такой же красивой, как нам бы хотелось:-) Отличные примеры этого прагматического подхода в Адаме Биен Реальном мире Java EE Patterns - Переосмысление лучших практик.