Каковы реальные плюсы и минусы каждой из основных фреймворков для фиксации?

см. также «Что следует учитывать при выборе фиктивный фреймворк для .Net "

Я пытаюсь выбрать фреймворк для использования в проекте .NET, который я недавно начал. Я хотел бы ускорить свое исследование различных фреймворков. Недавно я прочитал это сообщение в блоге http://codevanced.net/post/Mocking-frameworks-comparison.aspx и поинтересовался, есть ли у кого-нибудь из аудитории StackOverflow что-нибудь, что можно добавить к реальным преимуществам и предостережениям в отношении фреймворков.

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

  • RhinoMocks
  • Moq
  • Тип: Мок изолятор
  • NMock
  • Родинки

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


person BenAlabaster    schedule 11.11.2009    source источник
comment
Программное обеспечение для кодирования достаточно сложно. Я бы не хотел использовать тот, который постоянно издевается надо мной в процессе.   -  person DA.    schedule 12.11.2009
comment
Вы можете найти этот вопрос и ответы на него полезными: stackoverflow.com/questions/642620/. Это также указывает на несколько других связанных вопросов, в частности на stackoverflow.com/questions/37359/.   -  person Jeff Sternal    schedule 12.11.2009
comment
Спасибо, Джефф - они очень полезны; Я не встречал их, пока искал эту информацию.   -  person BenAlabaster    schedule 12.11.2009
comment
В книге artofunittesting.com есть много полезной информации по этому поводу, хотя у автора есть (четко указано) предвзятость.   -  person TrueWill    schedule 12.11.2009


Ответы (7)


Я совсем не знаю родинок, но расскажу о тех, о которых немного знаю (хотя для этого мне действительно нужен стол).

Moq

Плюсы

  • Тип-безопасный
  • Единый интерфейс
  • Поощряет хороший дизайн

Минусы

  • Not as full-featured as some of its competitors
    • It can't mock delegates
    • Он не может оправдать упорядоченные ожидания
    • возможно, другие вещи, о которых я не могу сейчас думать ...
  • Может имитировать только интерфейсы и виртуальные / абстрактные члены

Моки носорога

Плюсы

  • Тип-безопасный
  • Полный набор функций
  • Поощряет хороший дизайн

Минусы

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

Изолятор TypeMock

Плюсы

  • Типобезопасный (AFAIR)
  • Может издеваться над чем угодно

Минусы

  • Очень инвазивный
  • Возможная привязка к поставщику
  • Не поощряет хороший дизайн

NMock

Плюсы

  • Поощряет хороший дизайн
  • Работает на любой версии .NET (даже 1.1)

Минусы

  • Не типобезопасный
  • Может имитировать только интерфейсы и виртуальные / абстрактные члены

Обратите внимание, что преимущества и недостатки TypeMock весьма противоречивы. Я опубликовал свое мнение по этому поводу в моем блоге .

Я начал с NMock, когда это был единственный вариант еще в 2003 году, затем перешел на Rhino Mocks из-за его безопасности типов, а теперь использую Moq из-за более простого API.

person Mark Seemann    schedule 12.11.2009
comment
Что касается упорядоченных ожиданий в Moq: Фил Хаак показывает здесь хороший способ обойти это: haacked.com/archive/0001/01/01/moq-sequences.aspx - person flq; 12.11.2009
comment
@Mark: Не могли бы вы подробнее рассказать о своем наблюдении, что TypeMock очень агрессивен? В каком смысле? - person BenAlabaster; 12.11.2009
comment
@Mark: P.S. Я прочитал ваше сообщение в блоге о TypeMock и, учитывая аргументы, выдвинутые Роем Ошеровым, и ваши ответы [и ничего не зная о TypeMock], я должен сделать вывод, что ваш аргумент кажется более убедительным. - person BenAlabaster; 12.11.2009
comment
@BenAlabaster: он использует API профилирования для перехвата вызовов методов и т. Д. Во время выполнения. По сути, выполняемый код - это не тот код, который вы (или кто-то другой) написали. - person Mark Seemann; 12.11.2009
comment
+1 - отличный ответ и отличный пост в блоге! Я не совсем понимаю, что вы имеете в виду, говоря, что Moq не может издеваться над делегатами. Он может имитировать события, и вы всегда можете передать лямбду в любой метод с параметром делегата (там нет необходимости в структуре). - person TrueWill; 12.11.2009
comment
@TrueWill: Допустим, у вас есть класс, который вводится с делегатом вместо реального интерфейса / базового класса. С помощью Rhino Mocks вы можете фактически настроить для этого ожидания и передать динамически сгенерированный экземпляр. В прошлый раз, когда я проверил, это было невозможно в Moq. - person Mark Seemann; 12.11.2009
comment
@Mark Я могу придумать кучу мест, где я прохожу делегатов ... так что Moq может стать непростой пилюлей - по крайней мере, для этого проекта. - person BenAlabaster; 12.11.2009
comment
@BenAlabaster: Что ж, на практике это оказывается не такой уж большой проблемой, поскольку вместо этого вы всегда можете просто передать лямбда-выражение. - person Mark Seemann; 13.11.2009
comment
@Mark - Это информация из реального мира, которую я искал; Нельзя имитировать делегатов, но можно имитировать, передав вместо них лямбда-выражения. Это действительно полезно. - person BenAlabaster; 13.11.2009
comment
Я не согласен с тем, что поощряет хороший дизайн / Не поощряет хорошую оценку дизайна. Помимо того, что это в высшей степени субъективно и противоречиво, это игнорирует несколько очевидных реальных ситуаций, когда использование ограниченных средств имитации может привести к плохому коду. Например, инструмент, который не может имитировать невиртуальный метод, вынуждает либо создать отдельный интерфейс (что, скорее всего, будет бессмысленно), либо методы, не предназначенные для создания подклассов, будут объявлены как виртуальные; это не совсем обнадеживает хороший объектно-ориентированный дизайн ... - person Rogério; 07.01.2010
comment
@Rogerio: Я не согласен, хотя знаю, что это противоречиво. Часто оказывается, что разделенный интерфейс или виртуальный метод, который, как вы изначально думали, имел смысл только по причинам тестируемости, внезапно становятся удобными в производственном коде. Однако для правильного проектирования требуется умение, а не просто мешанина для поддержки модульных тестов. Однако при правильном выполнении тестируемость - это просто частный случай принципа открытости / закрытости: blog.ploeh.dk/2009/06/05/ - person Mark Seemann; 07.01.2010
comment
Фактически, вы соглашаетесь со мной 8 ^), поскольку вы признаете, что иногда (вы сказали, что это часто оказывается ...) введение отдельного интерфейса или виртуального метода может НЕ оказаться удобным в производственном коде. Таким образом, в таких случаях вам может понадобиться издеваться над классом, не делая этого. И это технически возможно (даже просто) сделать как в .NET, так и в Java. - person Rogério; 07.01.2010

До сих пор я использовал RhinoMocks и Moq. Moq в настоящее время является моим фаворитом из-за его простоты, которая в настоящее время является всем, что мне нужно. RhinoMocks - довольно мощный инструмент, но я никогда не был в состоянии полностью использовать его.

person flq    schedule 11.11.2009
comment
Я начал с RhinoMocks и быстро перешел на Moq, как только узнал о нем. Moq чертовски прост в использовании. - person Chris; 12.11.2009

Мы используем Rhino Mocks уже больше года. ЗА:

  • легко создавать макеты
  • может издеваться над общедоступными и внутренними методами
  • может имитировать интерфейсы или классы
  • может создавать частичные макеты (имитирующие только определенные методы из класса)

ПРОТИВ:

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

В общем, мы обнаружили, что использование макетных фреймворков способствует тестированию «белого ящика» (особенно для модульных тестов). В итоге мы получили тесты, которые подтверждали, КАК все было сделано, а не ЧТО они делали. Они были бесполезны для рефакторинга, и нам пришлось переписать большинство из них.

person vladhorby    schedule 12.11.2009
comment
Лично я предпочитаю проводить тестирование состояния с помощью заглушек, чем тестирование поведения с помощью проверяемых имитаций. Это может помочь избежать хрупких тестов, подтверждающих, как. - person TrueWill; 12.11.2009
comment
Ооо, необходимость разработки вашего кода для размещения фиктивного фреймворка для меня определенно нарушает условия сделки. +1 за ваше понимание по этому поводу, очень ценно. - person BenAlabaster; 12.11.2009
comment
@Ben - это ограничение будет у вас с чем угодно, кроме TypeMock. Если вы издеваетесь над интерфейсами, нет проблем. С конкретными классами вы можете имитировать только виртуальные методы. - person TrueWill; 12.11.2009
comment
@TrueWill - Хорошие принципы дизайна существуют, потому что они делают ваш код более простым, расширяемым, легким в обслуживании и т. Д., А не для поддержки вашего фреймворка. Следование хорошим принципам дизайна может упростить модульное тестирование, но использование фреймворка фиктивного дизайна в ваших проектных решениях может поставить под угрозу хорошие принципы дизайна и прочно связать ваш код и фреймворк фиктивного проекта. Разве зависимости не являются чем-то, от чего мы пытаемся избавиться с момента появления Dependency Injection, IoC и фабричных шаблонов? Почему внезапно стало нормально начинать проектировать наш код вокруг этой зависимости? - person BenAlabaster; 12.11.2009
comment
@Ben - Если ваш код следует принципу инверсии зависимостей, вы не столкнетесь с этим ограничением. Только когда у вас есть конкретные зависимости, которые вы не можете легко отделить (читайте: устаревший код), вам нужен TypeMock. Вам не нужно (или не хотите) развертывать фреймворк mocking; он используется только вашими модульными тестами. Ваш производственный код не должен быть связан с фреймворком mocking. - person TrueWill; 12.11.2009
comment
@TrueWill - Я согласен, хотя я имел в виду не связывание производственного кода с фреймворком для фиксации с целью развертывания. Я имел в виду, что если ваш код разработан для возможности имитировать ваши объекты с определенной структурой, а не использовать лучшие методы проектирования с точки зрения кодирования, тогда существует вероятность того, что станет сложнее заменить вашу фиктивную структуру на другую. если вы хотите сменить платформу тестирования. - person BenAlabaster; 12.11.2009
comment
@TrueWill - Вы правы, инверсия зависимостей - это то, что действительно работает. Он позволяет заглушить реальные внешние зависимости системы, такие как веб-службы и базы данных, и запускать тесты для целых компонентов или всей системы, а не только на уровне класса. Мы разработали простую базу данных на основе списка в памяти, которая может заменить реальную базу данных для тестов посредством внедрения зависимостей, не затрагивая производственный код. Модульные тесты на уровне класса / метода мешают рефакторингу, который распространяется на несколько классов. - person vladhorby; 12.11.2009
comment
@Ben - совершенно точно. Выбор фреймворка имитации / изоляции не должен влиять на дизайн производственного кода. - person TrueWill; 12.11.2009

Как и Фрэнк и Крис, я попробовал RhinoMocks и перешел на Moq. Я не был разочарован. Смотрите мою серию сообщений в блоге:

РЕДАКТИРОВАТЬ: Обратите внимание, что я обычно провожу тестирование на основе состояний с заглушками; Я редко провожу тестирование поведения с проверяемыми имитами.

person TrueWill    schedule 12.11.2009
comment
Можете ли вы подробнее рассказать, что подтолкнуло вас к переходу? Были ли проблемы с заглушками, с которыми вы столкнулись с Rhino Mocks, заставили вас покинуть корабль, или это то, что Moq просто справлялся лучше? - person BenAlabaster; 12.11.2009
comment
@Ben - Это была комбинация проблем с заглушками и сложности. С Rhino Mocks мне казалось, что я борюсь против библиотеки (и я всегда ссылался на документацию); Мне Moq показался более естественным. Я бы посоветовал попробовать оба и придерживаться той, которая больше всего соответствует вашим идиомам. - person TrueWill; 12.11.2009
comment
Спасибо за ссылку на ваши сообщения в блоге. Я пошел по вашему пути, покопался в некоторых обсуждениях и решил начать с Moq, чтобы посмотреть, как у меня дела. - person DaveN59; 19.03.2013
comment
@ DaveN59 - спасибо! Я недавно использую NSubstitute и хожу туда-сюда по состоянию и .. Тестирование поведения на основе моих потребностей. - person TrueWill; 19.03.2013

Я не использовал все эти фреймворки, но я посмотрел на RhinoMocks и Moq и выбрал Moq, потому что он кажется более элегантным и намного более простым. Я использую магистральную версию, которая включает обязательное исправление ограничения на 4 аргумента, наложенного на обратные вызовы в последней бета-версии 4.0.

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

person anelson    schedule 12.11.2009

Я использую TypeMock, так как разрабатываю на SharePoint. Поскольку TypeMock может имитировать что угодно, он оказался ценным ресурсом при модульном тестировании наших веб-частей SharePoint, приемников событий, рабочих процессов и т. Д.

С другой стороны, TypeMock может быть дорогим, однако доступна версия. который специфичен для SharePoint и стоит меньше, чем полный пакет TypeMock. Я очень рекомендую это.

Единственное, с чем я не согласен, - это мнение о том, что TypeMock не позволяет вам хорошо разрабатывать код. Часто классы, которые я создаю, и код в целом хорошо спроектированы. То, что я использую TypeMock, не означает, что я жертвую качеством своего дизайна - я все еще практикую IoC и SRP. Тот факт, что TypeMock может что-то имитировать, не означает, что я пишу свой код, чтобы отразить эту способность.

person Jason Evans    schedule 26.11.2009

Вы можете иметь в виду, что если вам нужно поддерживать многоязычную среду (например, VB), все настраиваемые фреймворки кода (я могу напрямую разговаривать с Moq и RhinoMocks) будут болезненными, учитывая (отсутствие) анонимности синтаксис делегата / лямбда в VB. Это будет более возможно в Visual Studio 2010 / VB 10, но все равно будет несопоставимо с красивым синтаксисом лямбда C #.

TypeMock, похоже, имеет некоторую поддержку VB

person Ben Von Handorf    schedule 11.11.2009
comment
Мне не обязательно нужна кросс-языковая совместимость, хотя это определенно будет приятным бонусом. Это могло бы меня поколебать, если бы две фреймворки в остальном были бы очень похожи, но вряд ли я бы променял это на другую полезную функцию. - person BenAlabaster; 12.11.2009