Как вы издеваетесь над Запечатанным классом?
Скупить закрытые классы может быть довольно больно. Я в настоящее время одобряю шаблон адаптера, чтобы справиться с этим, но что-то вроде просто держится странно.
Итак, что лучше всего вы издеваетесь над закрытыми классами?
Ответы Java более чем приветствуются. На самом деле, я ожидал, что сообщество Java уже справляется с этим и может предложить многое.
Но вот некоторые из мнений .NET:
Ответы
Ответ 1
Мое общее правило состоит в том, что объекты, которые мне нужны для макета, должны иметь общий интерфейс. Я думаю, что это правильный дизайн и делает тесты намного проще (и обычно это то, что вы получаете, если вы делаете TDD). Подробнее об этом можно прочитать в блоге Google Testing последнее сообщение (см. Пункт 9).
Кроме того, я работал в основном на Java за последние 4 года, и могу сказать, что могу рассчитывать, с одной стороны, количество раз, когда я создал окончательный (запечатанный) класс. Другое правило: у меня всегда есть веская причина, чтобы запечатать класс, а не запечатывать его по умолчанию.
Ответ 2
Для .NET вы можете использовать что-то вроде TypeMock, которое использует API профилирования и позволяет подключаться к вызовам почти ко всему.
Ответ 3
Я считаю, что Moles из Microsoft Research позволяет это сделать. На странице Moles:
Моли могут использоваться для обхода любых .NET. метод, в том числе не виртуальный/статический методы в закрытых типах.
UPDATE: появилась новая фреймворк под названием "Подделки" в предстоящем выпуске VS 11, который предназначен для замены Moles:
Fakes Framework в Visual Studio 11 является следующим поколением Moles и Stubs и в конечном итоге заменит его. Подделки отличаются от Moles, однако, поэтому переход от Moles to Fakes потребует внесения некоторых изменений в ваш код. Руководство по этой миграции будет доступно позднее.
Требования: Visual Studio 11 Ultimate,.NET 4.5
Ответ 4
Проблема с TypeMock заключается в том, что она оправдывает плохой дизайн. Теперь я знаю, что часто плохой дизайн другого человека, который он скрывает, но разрешающий его в процессе разработки, может очень легко разрешить ваши собственные плохие проекты.
Я думаю, что если вы собираетесь использовать фальшивую фреймворк, вы должны использовать традиционную (например, Moq) и создать изолирующий слой вокруг немаркируемой вещи и вместо этого высмеять изолирующий слой.
Ответ 5
Я почти всегда избегаю зависимости от внешних классов внутри моего кода. Вместо этого я бы скорее использовал адаптер/мост, чтобы поговорить с ними. Таким образом, я имею дело с моей семантикой, и боль в переводе изолирована в одном классе.
Это также облегчает переход моих зависимостей в долгосрочной перспективе.
Ответ 6
Есть ли способ реализовать герметичный класс из интерфейса... и вместо этого имитирует интерфейс?
Что-то во мне чувствует, что в первую очередь ошибочно запечатаны классы, но это только я:)
Ответ 7
Я обычно беру путь создания интерфейса и класса адаптера/прокси, чтобы облегчить насмешку закрытого типа. Тем не менее, я также экспериментировал с пропуском создания интерфейса и созданием прокси-типа, не запечатанного виртуальными методами. Это сработало хорошо, когда прокси-сервер действительно является естественным базовым классом, который инкапсулирует и использует часть закрытого класса.
При работе с кодом, который требовал этой адаптации, я устал от выполнения тех же действий для создания интерфейса и типа прокси, поэтому я реализовал библиотеку для автоматизации задачи.
Код несколько более сложный, чем образец, указанный в статье, которую вы ссылаетесь, поскольку она создает сборку (вместо исходного кода), позволяет генерировать код для любого типа и не требует такой конфигурации.
Для получения дополнительной информации см. эту страницу.
Ответ 8
Совершенно разумно издеваться над закрытым классом, потому что многие каркасные классы запечатаны.
В моем случае я пытаюсь высмеять класс .Net MessageQueue, чтобы я мог TDD использовать мою грациозную логику обработки исключений.
Если у кого-то есть идеи о том, как преодолеть ошибку Moq в отношении "Недопустимая настройка для неперехваченного члена", сообщите мне.
код:
[TestMethod]
public void Test()
{
Queue<Message> messages = new Queue<Message>();
Action<Message> sendDelegate = msg => messages.Enqueue(msg);
Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate =
(v1, v2) =>
{
throw new Exception("Test Exception to simulate a failed queue read.");
};
MessageQueue mockQueue = QueueMonitorHelper.MockQueue(sendDelegate, receiveDelegate).Object;
}
public static Mock<MessageQueue> MockQueue
(Action<Message> sendDelegate, Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate)
{
Mock<MessageQueue> mockQueue = new Mock<MessageQueue>(MockBehavior.Strict);
Expression<Action<MessageQueue>> sendMock = (msmq) => msmq.Send(It.IsAny<Message>()); //message => messages.Enqueue(message);
mockQueue.Setup(sendMock).Callback<Message>(sendDelegate);
Expression<Func<MessageQueue, Message>> receiveMock = (msmq) => msmq.Receive(It.IsAny<TimeSpan>(), It.IsAny<MessageQueueTransaction>());
mockQueue.Setup(receiveMock).Returns<TimeSpan, MessageQueueTransaction>(receiveDelegate);
return mockQueue;
}
Ответ 9
Я столкнулся с этой проблемой в последнее время и после чтения/поиска в Интернете, кажется, что нет простого способа, кроме использования другого инструмента, упомянутого выше.
Или грубой обработки вещей, как я:
Ответ 10
Несмотря на то, что в настоящее время он доступен только в бета-версии, я думаю, что его стоит иметь в виду shim функцию нового Faces framework (часть Visual Studio 11 бета-версия).
ШИМ-типы предоставляют механизм для обхода любого метода .NET определенному делегату. Типы прошивок генерируются кодом генератором Fakes, и они используют делегаты, которые мы называем shim-типами, чтобы указать новые реализации методов. Под капотом типы прокладок используют обратные вызовы, которые были введены во время выполнения в методах MSIL.
Лично я искал использование этого, чтобы издеваться над методами на закрытых классах фреймворка, таких как DrawingContext.