2013-02-27 2 views
1

Обычно я устанавливаю каждый атрибут класса как final (только для атрибутов, которые будут инициализированы внутри конструктора). Дело в том, что я сейчас реализую макет объекта для целей тестирования. Этот Mockup расширяет класс, который он издевается, и этот класс имеет некоторые конечные атрибуты. Поэтому я вынужден вызвать конструктор super() внутри конструктора объекта Mockup. Однако это разрушает полезность Mockup, потому что я не хочу, чтобы он инициализировал все атрибуты так, как это делает обычный класс. Я бы предпочел называть конструктор Mockup без вызова super() и делать все, что захочу.Расширение класса с конечными атрибутами. Mockup

Мой вопрос: целесообразно ли определять атрибуты как окончательные, если они заставят вас вызвать конструктор классов в макете?

EDIT: Я добавляю код. Проблема в этом случае заключается в том, что я использую синглтон, я знаю, что это не очень хорошая идея при тестировании, но в этом случае я не могу его изменить. Поэтому я намерен не называть этот метод в макете.

public class ReportsDataManager { 

private final Map<String, List<String>> translations; 

public ReportsDataManager() { 
this.translations = GenericUtils.getTranslation(); 
} 

}

+0

Можете ли вы опубликовать код SUT и предполагаемый тест? Какова последовательность публичных вызовов/сообщений (когда они отправляются в тестируемый класс), что приведет к состоянию, требуемому для теста? Вам не нужно внешнее манипулирование частными переменными SUT. – Gishu

+0

«но в этом случае я не могу его изменить». Измени это! ;) http://stackoverflow.com/questions/2925459/refactoring-singleton-overuse – flup

+0

Как выглядит класс под тестом? Как он использует ReportDataManager? – flup

ответ

2

Если вы хотите высмеять класс, дайте ему интерфейс и издевайтесь над интерфейсом. Также, mocks aren't stubs. Похоже, вы создаете заглушку, а не макет. Если вы хотите создать макет, выберите библиотеку, которая создает для вас mocks для интерфейсов.

+0

Мне нравится ваша точка зрения, я не думал об этом. Это действительно стоит сделать интерфейс только для создания Mockup? – iberbeu

+0

Интерфейс также описывает, как связаны оба класса. Я думаю, что это всегда (ну, очень часто) хорошая идея. – flup

+0

В этом конкретном случае это будет хороший первый шаг в расцеплении ссылки на синглтон. – flup

1

В общем, я бы сказал, что если практика используется делает тестирование код более трудным, то практика может быть запах.

Попробуйте решить точно, чего вы хотите достичь, установив переменные final. Может ли protected быть приемлемым?

+0

Тем не менее, мне нравится @ Marko [solution] (http://stackoverflow.com/a/15110572/823393), используя отражение. – OldCurmudgeon

3

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

+0

Я согласен с вами, хотя иногда тест (по моему мнению) должен вести вас так, как вы кодируете. Дело здесь в том, что в конструкторе я вызываю другой метод, который дает мне значение, но этот метод сложный, поэтому я не хочу называть его в Mockup to. Каков наилучший способ? удаление окончательного предложения? вызов этого метода вне конструктора? – iberbeu

+0

Удаление, по моему мнению, окончательного предложения - это не путь. Я не понимаю, что означает «сложный».Если вы уже протестировали «сложный» метод и доказали, что он работает, почему вы не можете издеваться над этим, чтобы просто вернуть требуемое значение и продолжить с ним? – duffymo

+0

С усложненным я имею в виду, что это не просто значение атрибута. Я редактировал свой вопрос с помощью кода. В этом случае я должен удалить Singleton и высмеять объект GenericUtils, а именно метод getTranslation(). Таким образом, он должен работать. Но что делать, если дело не в использовании Singleton, а при вызове частного метода того же класса. Как я могу избавиться от него? Я не могу переопределить этот метод ... – iberbeu

1

Вы можете обойти ограничение final стандартным отражением. Поскольку вы находитесь в контексте макета, это не вызовет много проблем, я полагаю. Просто остерегайтесь многопоточных проблем: JVM будет считать, что поле придерживается семантики final и будет оптимизировано с учетом этого.

+0

Мне не очень нравится эта идея, так как использование отражения обычно не рекомендуется для модульного тестирования, не так ли? – iberbeu

+0

Я не знаю такой рекомендации. Во всяком случае, как вы думаете, все эти насмешливые рамки используют? Отражение довольно мягкое по сравнению с генерацией байт-кода runrtime. –

+0

У вас есть дискуссия об этом: http://stackoverflow.com/questions/2811141/is-it-bad-practice-to-use-reflection-in-unit-testing В любом случае использование рефлексии для создания макетов может быть но не имеет смысла использовать непосредственно одну из уже существующих инфраструктур? – iberbeu

Смежные вопросы