Использование фиктивных объектов вне тестирования, плохая практика? - PullRequest
5 голосов
/ 15 декабря 2008

Я работаю над проектом, в котором много внешних сервисных сообщений. Хороший способ описать его лишь слегка «гиперболическим» способом - это приложение, в котором система должна отправлять сообщения в API Flicker, API Facebook и Netflix.

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

Messenger<NetflixApi>.SendCustom( netflix => netflix.RecommendMovie("my message"));

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

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

Я видел или читал только о том, что Mocks используются в режиме чистого TDD, а не используются как некий тупой объект. Подходы, которые я видел, вращались вокруг заглушения или насмешки над функциональностью HTTP-связи, от которой зависят все используемые мной API.

Моя главная проблема заключается в том, что все различные службы, к которым я собираюсь подключиться, в конечном итоге должны будут выполнить большую детальную работу, заменяя конкретную реализацию HTTP, и если бы я использовал подход-заглушку, у меня было бы 3 класса для каждого этих сервисов (IService, ConcreteService, StubService) и их обслуживание при реализации нового метода или изменении чего-либо было бы настоящей PITA.

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

Вопрос в том, что я что-то упустил? Я нарушил принцип дизайна, используя Mocks более ... удобным способом?

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

Имеет ли этот вопрос смысл?

Спасибо за все ответы.

Редактировать # 1:

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

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

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

Ответы [ 3 ]

6 голосов
/ 15 декабря 2008

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

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

Цель Null Object - создать пустую и простую реализацию чего-либо, такого как Mock, но для использования в производственной среде.

Самый простой пример примерно такой:

class Logger{
 private static ILogger _Logger;

 static Logger(){
  //DI injection here
  _Logger = new NullLogger(); //or
  _Logger = new TraceLogger();
 }
}

interface ILogger{
 void Log(string Message);
}

internal class TraceLogger:ILooger{
 public void Log(string Message){
  //Code here
 }
}

internal class NullLogger{
 public void Log(string Message){
  //Don't don anything, in purporse
 }
}

Надеюсь, это поможет вам

4 голосов
/ 15 декабря 2008

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

4 голосов
/ 15 декабря 2008

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

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

Хорошие библиотеки насмешек стирают грани между насмешками, заглушками и подделками.

Взгляните на некоторую информацию от Мартина Фаулера о различных типах двойников. Насмешки - это не заглушки , TestDoubles .

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

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

...