Подделка метода тестируемого объекта - PullRequest
6 голосов
/ 15 июля 2011

Есть ли причина, по которой вам не следует создавать частичную имитацию объекта или просто подделывать один метод на объекте, который вы тестируете, для проверки другого метода?Это может быть полезно, чтобы уберечь вас от создания целого нового фиктивного объекта или когда в методе, который вы притворяетесь, есть внешняя зависимость, от которой вы не можете разумно избавиться и хотели бы не участвовать в других юнит-тестах?

Ответы [ 5 ]

3 голосов
/ 16 июля 2011

Объекты, для которых вы хотите сделать это, пытаются сделать слишком много вещей.В частности, если у вас есть внешняя зависимость, вы обычно создаете объект, чтобы изолировать эту зависимость.Шаблон Фасад является одним из примеров этого.Если ваши объекты не были разработаны с учетом тестируемости, вам, возможно, придется провести некоторый рефакторинг.Взгляните на PDF Майкла Фезерса о работе с устаревшим кодом (PDF)У него также есть книга с тем же названием, в которой он гораздо более детален.

2 голосов
/ 16 июля 2011

Это очень плохая идея - смоделировать / подделать часть класса для проверки другого.

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

Это также увеличивает бремя обслуживания поддельной части класса.Если это действует для всей тестовой программы, реализация фальшивок также усложняет другие тесты фальсифицированного метода.

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

Если это происходит потому, что метод обращается к файлу или базе данных, вы должны определить интерфейс и передать экземпляр этого интерфейса конструктору или методу класса.Это позволяет вам тестировать различные сценарии в одном и том же тестовом приложении.

Если это происходит из-за того, что вы используете синглтоны, вам следует переосмыслить свой дизайн, чтобы сделать его более тестируемым: удаление синглетонов удалит неявные зависимости и кошмары обслуживания.

Если вы используете статические методы / автономные функции для доступа к данным в реестре или файле настроек, вам действительно следует удалить их из тестируемой функции и передать данные в качестве параметра или предоставить интерфейс поставщика настроек,Это сделает код более гибким и надежным.

Если вы хотите сломать зависимость для целей тестирования (например, подделка векторного метода для тестирования метода в матричном классе), то вы не должны притворятьсяэто - вы должны рассматривать тестируемый код как то, что определяется тестируемым классом его открытым интерфейсом: методы;предварительные условия, постусловия, инварианты, документация, параметры и спецификации исключений.

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

Например, предположим, что вы фальсифицировали std :: vector :: at (), но реализация переключилась на использование оператора [].Ваш тест будет сломан или тихо пройден.

1 голос
/ 18 июля 2011

Метод Извлечение и переопределение , описанный в главе 3 книги Роя Ошерова Искусство модульного тестирования , похоже, является способом подделки части тестируемого класса (стр. 71-77).Ошерове не рассматривает проблемы, поднятые в некоторых других ответах на этот вопрос.

Кроме того, Майкл Фезерс обсуждает это в Эффективная работа с устаревшим кодом .Он называет результирующий класс тестовым подклассом (227) и техникой Подкласс и метод переопределения (401).Теперь, предоставлено, Перья не дают изложение нетронутых методов, которые рекомендуются в новом коде.Но он все еще считает это серьезным лечением как потенциально полезную технику.

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

Я изначально писал вопрос, когда был новичком в модульном тестировании и почти ничего не знал о внедрении зависимостей.Теперь, после некоторого опыта с обоими, я бы добавил, что необходимость использовать эту технику тестирования может быть запахом.Это может быть признаком того, что необходимо переработать ваш подход к зависимостям.Если метод, который должен быть подделан, - это тот, который унаследован от базового класса, это может означать, что вам следует более серьезно относиться к поговорке «композиция благосклонности над наследованием».Вы должны внедрять свои зависимости, а не наследовать их.

1 голос
/ 16 июля 2011

Если метод, который вы хотите подделать, является виртуальным (например, не статичным и не конечным), то вы можете создать подкласс для своего объекта в своем тесте, переопределить метод в подклассе и применить подкласс в тесте.Библиотеки фиктивных объектов не требуются.

(В идеале вам следует подумать о рефакторинге, это не очень хорошее долгосрочное решение. Но это способ протестировать устаревший код, чтобы вы могли легче запустить процесс рефакторинга.)

0 голосов
/ 16 июля 2011

Есть несколько действительно хороших пакетов для облегчения такого рода вещей. Например, из документов Mockito :

//You can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);

//stubbing
when(mockedList.get(0)).thenReturn("first");

совершает настоящую магию, в которую трудно поверить. Когда вы звоните

String firstMember = mockedList.get(0);

вы вернетесь «первым» из-за того, что вы сказали в выражении «когда».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...