Я работаю над проектом, в котором много сообщений от внешних служб. Хорошим способом описать это лишь слегка «гиперболическим» способом было бы приложение, в котором система должна отправлять сообщения в Flicker API, Facebook API и Netflix API.
Для поддержки отключенных сценариев, проблем с журналированием, удобства использования, настройки разработчиками и т. д. Я экспериментировал с подходом, в котором широко используются обобщенные типы и деревья выражений. Конечный результат выглядит так:
Messenger<NetflixApi>.SendCustom( netflix => netflix.RecommendMovie("my message"));
В целом я доволен конечным результатом, но чувствую, что допустил ошибку или где-то упустил из виду принцип дизайна, касающийся тестирования и отключенных сценариев.
Во время тестирования, будь то автоматическое, модульное или человеческое, я реализовал объектную фабрику, которая изначально использует DI для выполнения правильных действий в «живом режиме», а также использовал Mocks для обеспечения своего рода стерильного мессенджера, который ничего не делает в все в тестовом режиме.
Я видел или читал только о том, что Mocks используются в чистом режиме TDD и не используются как тупой объект. Подходы, которые я видел, будут вращаться вокруг заглушек или имитации функциональности связи HTTP, от которой зависят все API, которые я использую.
Моя основная проблема заключается в том, что все различные службы, к которым я ожидаю подключиться, в конечном итоге должны будут выполнять много гранулярной работы, заменяя конкретную реализацию HTTP, и если бы я использовал подход с заглушками, у меня было бы 3 класса для каждой из этих служб. (IService, ConcreteService, StubService) и их обслуживание при реализации нового метода или изменении чего-либо было бы настоящим PITA.
В текущей реализации я использую Mocks, чтобы получить «стерильный режим» бесплатно почти без необходимости реализовывать что-либо дополнительное, просто чтобы соответствовать определенному принципу тестирования.
Вопрос в том, я что-то упускаю? Я нарушил принцип дизайна, используя Mocks более ... удобным способом?
Может ли кто-нибудь посоветовать, как получить стерильный режим из множества различных внешних сервисов, не прыгая через множество препятствий?
Имеет ли смысл этот вопрос?
Спасибо за ответы на все вопросы.
Редактировать # 1:
Я не совсем понял свой первоначальный вопрос. Любые пустые или фиктивные объекты должны использоваться исключительно в среде разработки / отладки / тестирования. В процессе производства код, который отправляет эти сообщения, будет их фактической реализацией.
Я проголосовал за всех, потому что, похоже, есть много разных решений этой проблемы, и я буду исследовать каждое из них.
Пожалуйста, не думайте, что на этот вопрос еще есть ответ, я был бы признателен за как можно больше советов.





Думаю, вам может понадобиться уточнить свой вопрос. Мне неясно, говорите ли вы об использовании тестовых двойников при тестировании без заглушек или ожидаемых результатов тестирования (чтобы использовать их как подделки для соответствия требуемым интерфейсам), или вы говорите об использовании макетов в производственном сценарии для заполнения сервисов, которые недоступны (ваш сценарий отключения).
Если речь идет о тестовых ситуациях: Моки - это тестовые двойники. Нет ничего плохого в тестировании с использованием подделок, а не имитов или заглушек. Если вам не нужно использовать службу в конкретном тесте, и она предназначена только для предоставления заданного интерфейса, от которого тестируемый объект зависит, тогда все в порядке. Это не нарушает принципа тестирования.
Хорошие библиотеки имитаторов стирают границы между имитами, заглушками и фейками.
Ознакомьтесь с информацией от Мартина Фаулера о различных типах тестовых пар. Моки - это не заглушки, TestDoubles.
Мне очень нравится, что moq позволяет создавать континуум между фиктивными, фальшивыми, заглушками и фиктивными объектами без необходимости перепрыгивать через обручи для получения определенного поведения. Проверить это.
Если вы говорите об использовании моков в вашем отключенном сценарии для производственного использования ... я бы волновался. Подделка будет возвращать нулевые объекты или значения по умолчанию для любых ваших вызовов. Это приведет к усложнению всего кода, потребляющего эти службы (им нужно будет обрабатывать проверку нулевых возвращаемых значений и пустых массивов ...). Я думаю, что было бы более разумно, если бы ваш сценарий отключения / стерильности был закодирован для обработки того, что сами зависимости недоступны, а не принимать их фиктивные реализации и продолжать, как будто все работает.
Существует шаблон проектирования под названием Null Object. Нулевой объект - это объект, реализующий интерфейс, поэтому его можно использовать в сценарии, подобном вашему.
Важная особенность нулевого объекта заключается в том, что НЕ возвращайте значение null в тех местах, где это может нарушить работу системы.
Цель объекта Null состоит в том, чтобы иметь пустую и простую реализацию чего-либо, точно так же, как 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
}
}
Я надеюсь, это может тебе помочь
Мне кажется, вы захотите взглянуть на шаблон прокси. Вам нужно что-то, что действует как различные службы, даже когда они отключены от реальных служб. Поэтому вашему коду было бы лучше разговаривать с прокси, а не с реальной вещью. Затем прокси может делать все, что ему нужно, в зависимости от текущего статуса подключения.
В тот момент, когда я увидел тему этой беседы, появилось красное предупреждение "Нулевой объект" ...