Зачем мне писать фальшивый класс и тестировать его? - PullRequest
10 голосов
/ 24 ноября 2008

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

Но я только начал писать модульные тесты для проекта, который будет действовать как хранилище (получать объекты из базы данных). Я пишу «фальшивый» репозиторий, который реализует интерфейс ISomethingRepository. Он использует Dictionary<Guid, Something> для внутреннего хранения. Он реализует методы интерфейса Add(Something) и GetById(Guid).

Почему я пишу это? Ничто из того, что я пишу, на самом деле не будет использовано программным обеспечением при его развертывании, верно? Я действительно не вижу ценности этого упражнения.

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

запуталась ...

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

Спасибо!

Ответы [ 10 ]

13 голосов
/ 24 ноября 2008

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

3 голосов
/ 24 ноября 2008

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

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

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

Редактировать: обновленные термины для большей согласованности.

  • Mock - созданный фальшивый фреймворк
  • Поддельный - созданный вручную, на самом деле может функционировать.
  • Проверка поддержки - издевательства, подделки, заглушки и все остальное. Не производство.
2 голосов
/ 24 ноября 2008

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

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

1 голос
/ 31 августа 2009

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

Первое - это проверить сервисы, которые используют реализацию эквивалента «ISomethingRepository», которую вы упоминаете. Тем не менее, наши реализации репозитория создаются фабрикой. Это означает, что мы пишем тесты для «ISomethingRepository», но не для «MockSomethingRepository» напрямую. Проводя тестирование на интерфейсе, мы можем легко утверждать, что покрытие кода для наших тестов покрывает 100% интерфейса. Обзоры кода обеспечивают простую проверку того, что тестируются новые члены интерфейса. Даже если разработчики используют макет, возвращаемый фабрикой, сервер сборки имеет другую конфигурацию, которая проверяет конкретную реализацию, которую фабрика возвращает в ночных сборках. Он обеспечивает лучшее из обоих миров с точки зрения охвата тестами и локальных характеристик.

Во-вторых, я удивлен, что никто не упомянул. Моя команда отвечает за средний уровень. Наши веб-разработчики несут ответственность за интерфейс веб-продуктов. Создавая фиктивные реализации репозитория, нет искусственного препятствия в ожидании моделирования и реализации базы данных до начала внешней работы. Могут быть написаны представления, которые будут построены на макете, чтобы обеспечить минимальное количество «реальных» данных, чтобы соответствовать ожиданиям веб-разработчиков. Например, могут быть предоставлены данные, содержащие строковые данные минимальной и максимальной длины, чтобы убедиться, что они не нарушают их реализацию и т. Д.

Поскольку фабрики, которые мы используем, связаны с тем, какой «ISomethingRepository» возвращать, у нас есть локальные тестовые конфигурации, сборочные тестовые конфигурации, производственные конфигурации и т. Д. Мы намеренно стараемся убедиться, что ни одна команда в проекте не имеет необоснованного ожидания раз из-за времени реализации другой команды. Большая часть времени ожидания по-прежнему предоставляется командой разработчиков, но мы можем запускать наши доменные объекты, репозитории и сервисы более быстрыми темпами, чем фронтальная разработка.

Конечно, YMMV. ; -)

1 голос
/ 18 июня 2009

Вместо того, чтобы писать самодельный класс, вы можете использовать инструмент (например, Rhino или Typemock ), чтобы смоделировать его. Это намного проще, чем писать все издевательства самостоятельно. И, как говорили другие, нет необходимости тестировать поддельный код, который не будет кодом, если вы используете инструмент.

1 голос
/ 24 ноября 2008

Вы не должны тестировать фиктивный класс.

Что вы обычно делаете: вы создаете фиктивные классы для всех классов, с которыми взаимодействует тестируемый класс.

Допустим, вы тестируете класс с именем Bicycle , который принимает в конструктор объекты классов Wheel, Saddle, HandleBar и т. Д.

И затем в классе Bike вы хотите протестировать его метод GetWeight , который, вероятно, выполняет итерацию по каждой части и вызывает свойство / метод Weight из них, а затем возвращает итог.

Что вы делаете:

  • вы пишете фиктивный класс для каждой части (Колесо, седло и т. Д.), Который просто реализует бит веса
  • тогда вы передаете эти ложные уроки Велосипеду
  • проверка метода GetWeight на классе Bicycle

Таким образом, вы можете сосредоточиться на тестировании GetWeight на классе Bicycle способом, независимым от других классов (скажем, они еще не реализованы, не детерминированы и т. Д.)

1 голос
/ 24 ноября 2008

Кто смотрит на наблюдателей?

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

Вы не тестируете объект Mock с помощью модульного теста, но используете его для тестирования классов, которые зависят от него.

0 голосов
/ 06 марта 2015

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

Например, в проекте Spring вы можете использовать Spring Testcontext для запуска контекста Spring внутри модульного теста, а затем подключиться к реальной базе данных и проверить, что запросы возвращают правильные результаты. Возможно, вам нужна собственная база данных для модульных тестов, или вы можете соединить их с БД разработчика.

0 голосов
/ 17 августа 2013

Посмотрите следующую статью для хорошего объяснения этого:

http://msdn.microsoft.com/en-us/magazine/cc163358.aspx

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

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

0 голосов
/ 24 ноября 2008

Вы пишете «фальшивый» класс с именем Stub или Mock object, потому что вы хотите протестировать реализацию простым способом без тестирования реального конкретного класса. Цель состоит в том, чтобы упростить тестирование, тестируя только интерфейс (или абстрактный класс).

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

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