Должны ли вы только издеваться над типами, которыми вы владеете? - PullRequest
37 голосов
/ 15 декабря 2009

Я прочитал TDD: только макеты, которыми вы владеете запись Марка Нидхэма и хотелось бы знать, является ли это наилучшей практикой или нет?

Обратите внимание, что он не против насмешек, а против насмешек напрямую - он говорит, что писать обертку и насмешки - это хорошо.

Ответы [ 7 ]

28 голосов
/ 17 декабря 2009

Мой ответ "нет". Вы должны высмеивать все, что имеет смысл в контексте данного модульного теста. Не должно иметь значения, «владеете» ли вы имитируемым типом или нет.

В наши дни в среде Java или .NET все (и я действительно имею в виду все) можно легко смоделировать. Таким образом, нет никаких технических причин для написания дополнительного кода оболочки.


Некоторые дополнительные идеи, о которых я недавно думал (ноябрь 2010 г.), показывают, насколько нелогичными могут быть «только те типы насмешек, которые у вас есть»:

  1. Предположим, что вы делаете создаете оболочку для стороннего API, а затем вы дразните оболочку в модульных тестах. Позже, однако, вы полагаете, что обертка может быть повторно использована в другом приложении, поэтому вы перемещаете ее в отдельную библиотеку. Так что теперь обертка больше не принадлежит вам (поскольку она используется в нескольких приложениях, потенциально поддерживаемых разными командами). Должны ли разработчики создавать новую обертку для старой?!? И продолжайте делать это рекурсивно, добавляя слой за слоем практически бесполезного кода?
  2. Предположим, что кто-то уже создал хорошую оболочку для какого-то нетривиального API и сделал ее доступной в качестве библиотеки многократного использования. Если указанная оболочка - именно то, что мне нужно для моего конкретного случая использования, я должен сначала создать оболочку для оболочки с почти идентичным API, просто так, чтобы я ее «владел»?!?

В качестве конкретного и реалистичного примера рассмотрим API электронной почты Apache Commons, который является не более чем оболочкой для стандартного API Java Mail. Так как он мне не принадлежит, должен ли я всегда создавать оболочку для API электронной почты Commons, всякий раз, когда я пишу модульные тесты для класса, который должен отправлять электронную почту?

22 голосов
/ 15 декабря 2009

Зависит от того, имеете ли вы в виду макет или насмешку и торговлю; & hellip;

Учитывая, что вы просто используете фиктивный фреймворк (например, Mockito) для создания заглушек, тогда создание заглушек типов, которые вам не принадлежат, вполне нормально и разумно.

Если, однако, вы используете макет фреймворка (например, Mockito) для создания макета и торговли; объекты, тогда вам лучше всего буквально следовать советам издевательства и торговли; евангелисты. Лично я потерял связь с этим движением, поэтому не могу сказать вам, следует ли считать совет Марка Нидхэма кошерным или нет.

Ирония в стороне, то, что пишет Марк о насмешках над EntityManagers в Hibernate, звучит разумно само по себе. Но я сомневаюсь, что мы можем обобщить правило типа «никогда не издевайтесь над типами, которые вам не принадлежат» из этого конкретного случая. Иногда это может иметь смысл, иногда нет.

14 голосов
/ 11 августа 2015

Мне нравится объяснение , которое проект Mockito дает на этот вопрос.

Не издевайтесь над типом, который вам не принадлежит!

Это не жесткая линия, но пересечение этой линии может иметь последствия! (скорее всего, будет)

  1. Представьте себе код, который издевается над сторонней библиотекой. После определенного обновления третьей библиотеки логика может немного измениться, но тест Suite будет работать просто отлично, потому что это издевательство. Итак, позже думая, что все хорошо, строительная стена в конце концов зеленая, программное обеспечение развернуто и ... Boom
  2. Это может быть признаком того, что текущий дизайн недостаточно отделен от этой сторонней библиотеки.
  3. Также еще одна проблема заключается в том, что сторонняя библиотека может быть сложной и требовать большого количества насмешек, чтобы даже работать должным образом. Это приводит к чрезмерному указанные тесты и сложные приспособления, что само по себе ставит под угрозу компактная и читаемая цель. Или к тестам, которые не покрывают код достаточно из-за сложности издеваться над внешней системой.

Вместо этого наиболее распространенным способом является создание оберток вокруг внешнего lib / system, хотя следует помнить о риске абстракции утечка, где слишком много низкого уровня API, концепций или исключений, идет за границей обертки. Для проверки интеграции со сторонней библиотекой, напишите интеграционные тесты и сделайте их максимально компактный и читаемый.

8 голосов
/ 15 декабря 2009

Я собирался сказать «нет», но, посмотрев быстро на пост в блоге, я понял, о чем он.

Он говорит конкретно о насмешливых EntityManager в Hibernate. Я против этого. Менеджеры EntityManager должны быть спрятаны внутри DAO (или аналогичных), а DAO - это то, что нужно высмеивать. Тестирование вызовов по одной линии в EntityManager - пустая трата вашего времени и прервется, как только что-то изменится.

Но если у вас есть сторонний код, который вы хотите проверить, как вы взаимодействуете с ним, обязательно.

1 голос
/ 05 марта 2018

ИМХО, вопрос о собственности не имеет значения.

Соответствующим вопросом является вопрос сцепления , т. Е. Что указывает ваш тестовый код. Вы, конечно, не хотите тестовый код, который определяет детали API некоторой библиотеки, которую вы случайно используете. Это то, что вы получаете, когда вы, например. используйте Mockito для насмешки над библиотекой непосредственно в вашем тестовом классе.

Широкое предложение по для этой проблемы - создать оболочку вокруг библиотеки и затем смоделировать оболочку. Но это имеет следующие недостатки:

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

Поэтому вместо этого я бы рекомендовал отделить тесты от интерфейсов в производительном коде в целом . Не помещайте макеты непосредственно в тестовый код, а создайте отдельный класс-заглушку, который реализует или макетирует производительный интерфейс. Затем добавьте второй интерфейс к заглушке, который позволит тестам выполнить необходимые настройки или утверждения. Тогда вам нужно будет адаптировать только один класс в случае изменения производительного интерфейса - и вы даже можете позволить себе смоделировать / заглушить интерфейс сложной или часто меняющейся библиотеки.


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

0 голосов
/ 11 июля 2010

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

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

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

0 голосов
/ 15 декабря 2009

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

Мое эмпирическое правило гласит: «Делайте вещи, которые сделают тест быстрым, но не сделают его нестабильным». Помните, что не все подделки одинаковы, и издевательства не являются заглушками .

...