Как вы издеваетесь над Запечатанным классом?

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

Итак, как лучше всего издеваться над закрытыми уроками?

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

Но вот некоторые из мнений .NET:

9.08.2008 00:14:22
cregox 4.09.2013 19:59:18
10 ОТВЕТОВ
РЕШЕНИЕ

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

Кроме того, я работал в основном на Java последние 4 года и могу сказать, что могу рассчитывать с одной стороны, сколько раз я создал окончательный (запечатанный) класс. Другое правило: у меня всегда должна быть веская причина запечатать класс, а не запечатывать его по умолчанию.

11
9.08.2008 09:40:37
Я бы сказал, что у вас должна быть веская причина не закрывать уроки. Оставление класса открытым означает, что вам нужно подумать о том, как он будет использоваться наследниками, что открывает множество решений относительно всего кода в классе (виртуальность, защищенные свойства или закрытые переменные-члены и т. Д.). Трудно правильно разработать класс для наследования. Вы не должны иметь возможность расширять класс только ради расширения; вывод должен означать что-то конкретное для моделируемой проблемы. В противном случае, предпочтение композиции вместо.
Bryan Watts 26.05.2009 14:46:46
Брайан - так как ты тогда будешь издеваться над закрытым классом? Я согласен с вами с теоретической точки зрения, но если вы пишете что-то, зависящее от вашего запечатанного класса, то ваши тесты также зависят от запечатанного класса.
Beep beep 22.11.2009 07:48:09
@abyx: К сожалению, разработчик не всегда выбирает, запечатан класс или нет. Возьмите, например, System.Web.HttpServerUtility в ASP.NET ...
chiccodoro 7.07.2011 13:39:39
@BryanWatts Я категорически не согласен с этим. Запечатывание класса просто лишает кодировщиков возможности наследовать класс. Они могут посчитать его полезным, как вы и не предполагали. Вам не нужно беспокоиться о том, как они что-то напортачат; это (вероятно) не ваша ответственность. Я бы на самом деле покончил с sealedключевым словом.
Jez 22.04.2015 09:58:03
@Jez: Если я не рассматривал расширение при написании класса, то зачем ему доверять?
Bryan Watts 22.04.2015 21:14:49

Есть ли способ реализовать запечатанный класс из интерфейса ... и вместо этого смоделировать интерфейс?

Что-то во мне чувствует, что запечатывание уроков в первую очередь неправильно, но это только я :)

0
9.08.2008 02:21:32
Я думаю, что закрытые классы - это здорово ... проблема в тестировании. Воняет, что мы должны изменить весь наш дизайн из-за ограничений в тестировании проектов .NET. Во многих случаях DI - это просто способ обойти тот факт, что статические классы / методы сложно тестировать.
Beep beep 22.11.2009 07:53:40

Для .NET вы могли бы использовать что-то вроде TypeMock , который использует API профилирования и позволяет подключаться к вызовам практически ко всему.

19
28.08.2008 06:44:22
+1. Используйте правильные инструменты. Не позволяйте инструментам диктовать вам, как вы должны делать вещи. API-интерфейсы предназначены для людей, а не для инструментов - разработайте их как таковые. Используйте DI и интерфейсы и полную развязку там, где это имеет смысл, а не только потому, что вам это нужно для инструментов тестирования.
Pavel Minaev 30.10.2009 18:09:46
Павел - проблема в том, что «правильный» путь в .NET обычно ведет вас по пути «Использовать TypeMock для тестирования». Следовать по пути, где есть только один доступный инструмент тестирования, тоже не кажется хорошим.
Beep beep 22.11.2009 07:49:13
Некоторым людям может не понравиться платить 80 долларов в месяц за тестовые рамки.
Matt Grande 9.12.2009 19:16:08
Я думаю, что Moles позволяет вам работать с закрытыми классами - и если у вас есть подписка MSDN, это бесплатно.
Mathias 6.04.2010 20:13:30
AFAIK Одной из основных проблем этих фреймворков, которые могут издеваться над запечатанными классами, статиками и т. Д., Является производительность. Лично я предпочитаю создавать интерфейс и использовать его в моем производственном коде с наследуемым прокси-объектом, внедренным во время производства, и имитацией, вставленной во время тестирования.
Adam Ralph 17.05.2011 07:23:38

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

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

5
28.08.2008 07:04:19
Не шлепать интерфейсы на все, что видно, только потому, что они вам нужны из-за недостатков ваших средств тестирования, это не плохой дизайн. На самом деле, как раз наоборот - разумный дизайн - это дизайн, а не соответствие вашим инструментам. Клянусь, иногда я думаю, что TDD, как это часто догматически практикуется, на самом деле следует называть «инструментальным проектированием». Также см. Weblogs.asp.net/rosherove/archive/2008/01/17/…
Pavel Minaev 30.10.2009 18:08:10
Павел - есть ли у вас другой инструмент, кроме TypeMock, который может обеспечить этот тип тестирования? Тестирование классов, построенных с использованием правильных конструкций (например, с использованием статических методов, новых вызовов в коде, ограничение интерфейсов тем, где требуется несколько реализаций и т. Д.), Зачастую практически невозможно протестировать.
Beep beep 22.11.2009 07:51:26
Я согласен с Брэдом здесь. Создание фиктивного объекта подразумевает, что вы тестируете публичное поведение этого типа. То есть вы конкретно говорите: «Мне нужно, чтобы публичный API этого объекта вел себя определенным образом». Это поведение не зависит от того, как реализован API. Это означает, что у вас есть уже определенная (хотя и неявная) абстракция, которая должна вести себя определенным образом. В системе статических типов это необходимо сделать явным, создав абстрактный тип.
xofz 6.04.2010 20:18:44

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

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

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

Для получения дополнительной информации, пожалуйста, обратитесь к этой странице .

1
8.12.2009 15:48:01

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

Это также облегчает переключение моих зависимостей в долгосрочной перспективе.

4
11.12.2009 04:08:01

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

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

Если у кого-то есть идеи о том, как преодолеть ошибку 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;
    }
1
6.04.2010 20:05:01
Я нашел решение и разместил здесь: dotnetmonkey.net/post/Hard-to-Moq.aspx
Adam Lenda 6.04.2010 21:09:32
спасибо за решение! страница все еще мертва
Viking 27.12.2018 12:53:27

Я считаю, что Moles из Microsoft Research позволяет вам сделать это. Со страницы Кротов:

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

ОБНОВЛЕНИЕ: в следующей версии VS 11 появилась новая платформа под названием «Fakes», предназначенная для замены Moles:

Подделки Framework в Visual Studio 11 является следующим поколением родинок и окурки, и в конечном итоге заменить его. Однако Fakes отличается от Moles, поэтому переход от Moles к Fakes потребует некоторых изменений в вашем коде. Руководство по этой миграции будет доступно позже.

Требования : Visual Studio 11 Ultimate, .NET 4.5

13
20.11.2012 16:50:47

Хотя его в настоящее время доступна только в бета - версии, я думаю , что его стоящее , имея в виду прокладка особенность новой структуры Подделки (часть Visual Studio 11 бета - версии).

Типы Shim предоставляют механизм для обхода любого метода .NET для определенного пользователем делегата. Типы Shim генерируются кодом генератором Fakes, и они используют делегаты, которые мы называем типами shim, для определения реализаций нового метода. Под капотом типы прокладок используют обратные вызовы, которые были введены во время выполнения в теле метода MSIL.

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

1
4.04.2012 01:24:41

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

  • Создайте экземпляр закрытого класса без вызова конструктора.
  • System.Runtime.Serialization.FormatterServices.GetUninitializedObject (instanceType);

  • Присвойте значения вашим свойствам / полям через отражение

  • YourObject.GetType (). GetProperty ("PropertyName"). SetValue (dto, newValue, null);
  • YourObject.GetType (). GetField ("FieldName"). SetValue (dto, newValue);
2
12.05.2015 19:42:34
Это единственное решение, которое имеет смысл и работает для насмешки над внутренним содержимым Microsoft без добавления дополнительных библиотек, таких как Fakes - спасибо!
Ben 28.10.2015 19:14:33