Зачем нам нужны насмешливые рамки? - PullRequest
17 голосов
/ 11 ноября 2009

Я работал с кодом, на котором написан тест NUnit. Но я никогда не работал с насмешливыми фреймворками. Кто они такие? Я понимаю внедрение зависимости и как это помогает улучшить тестируемость. Я имею в виду, что все зависимости могут быть проверены во время модульного тестирования. Но тогда зачем нам насмешливые рамки? Разве мы не можем просто создавать фиктивные объекты и предоставлять зависимости. Я что-то здесь упускаю? Спасибо.

Ответы [ 11 ]

12 голосов
/ 11 ноября 2009
  • Облегчает издевательство
  • Они обычно позволяют выразить тестируемый утверждения, которые относятся к взаимодействие между объектами.

Вот вам пример:

var extension = MockRepository
    .GenerateMock<IContextExtension<StandardContext>>();
  var ctx = new StandardContext();
  ctx.AddExtension(extension);
  extension.AssertWasCalled(
    e=>e.Attach(null), 
    o=>o.Constraints(Is.Equal(ctx)));

Вы видите, что я явно проверяю, что был вызван метод Attach IContextExtension и что входной параметр был назван контекстным объектом. Мой тест провалится, если этого не произойдет.

11 голосов
/ 11 ноября 2009

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

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

7 голосов
/ 11 ноября 2009

Иногда при работе со сторонними библиотеками или даже при работе с некоторыми аспектами .NET Framework очень сложно писать тесты для некоторых ситуаций - например, HttpContext или объект Sharepoint. Создание фиктивных объектов для них может стать очень громоздким, поэтому макеты фреймворка позаботятся об основах, чтобы мы могли сосредоточиться на том, что делает наши приложения уникальными.

3 голосов
/ 11 ноября 2009

Имитируемые объекты заменяют любые большие / сложные / внешние объекты, к которым необходим код для запуска.

Они выгодны по нескольким причинам:

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

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

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

3 голосов
/ 11 ноября 2009

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

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

Проверьте Rhino Mocks для примера того, насколько мощным может быть фреймворк.

2 голосов
/ 11 ноября 2009

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

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

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

1 голос
/ 07 октября 2015

Я бы сказал, что нет. Написание тестовых двойников не является большой работой в 9 раз из 10. Большую часть времени это делается почти полностью автоматически, просто попросив resharper реализовать интерфейс для вас, а затем вы просто добавляете мелкие детали, необходимые для этого двойника (потому что вы не выполняем кучу логики и не создаем эти запутанные двойные супер-тесты, верно? Верно?)

«Но почему я хотел бы, чтобы мой тестовый проект раздулся кучей тестовых пар», спросите вы. Ну, ты не должен. принцип СУХОГО также подходит для испытаний. Создайте ХОРОШИЕ двойники теста, которые можно использовать многократно и имеют описательные имена Это делает ваши тесты более читабельными.

Одна вещь, которая усложняет задачу, это чрезмерное использование двойных тестов. Я склонен согласиться с Роем Ошеровом и дядей Бобом, вы действительно не хотите создавать фиктивный объект с какой-то особой конфигурацией все это часто. Это сам по себе дизайнерский запах. Используя фреймворк, очень легко просто использовать удвоенные тесты со сложной логикой практически в каждом тесте, и в конце вы обнаруживаете, что на самом деле вы не тестировали свой производственный код, вы просто протестировали чудовищный беспорядок чудовищных франкенштейнов, содержащий: макеты, содержащие больше макетов. Вы никогда не будете «случайно» делать это, если будете писать свои двойники.

Конечно, кто-то укажет, что бывают случаи, когда вам «приходится» использовать фреймворк, а не делать это будет просто глупо. Конечно, есть такие случаи. Но у вас, вероятно, нет этого случая. Большинство людей этого не делают, и только для небольшой части кода, или сам код действительно плох.

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

1 голос
/ 21 апреля 2010

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

Например, если у меня есть класс A, содержащий бизнес-правила и логику, которые я хочу протестировать, но этот класс A зависит от классов доступа к данным, других бизнес-классов, даже классов u / i и т. Д., Этих других классов может быть подвергнуто насмешливому выполнению определенным образом (или никоим образом не в случае неконтролируемого поведения) для проверки логики в вашем классе А на основе каждого мыслимого способа, которым эти другие классы могли бы вести себя в производственной среде.

Чтобы дать более глубокий пример, предположим, что ваш класс A вызывает метод для класса доступа к данным, такой как

public bool IsOrderOnHold(int orderNumber) {}

тогда макет этого класса доступа к данным может быть настроен так, чтобы каждый раз возвращать true или каждый раз возвращать false, чтобы проверить, как ваш класс A реагирует на такие обстоятельства.

1 голос
/ 11 ноября 2009

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

0 голосов
/ 11 ноября 2009

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

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

...