Вопрос

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

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

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

Но вот некоторые из них .СЕТЕВЫЕ мнения:

Это было полезно?

Решение

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

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

Другие советы

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

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

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

Обновить: в предстоящем выпуске VS 11 появится новый фреймворк под названием "Fakes", который предназначен для замены Moles:

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

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

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

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

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

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

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

  • Создайте экземпляр запечатанного класса без вызова конструктора.
  • Система.Среда выполнения.Сериализация.Службы форматирования.Получаем uninitializedobject(instanceType);

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

  • YourObject.GetType().getProperty("Имя свойства").setValue(dto, newValue, null);
  • YourObject.GetType().getField("Имя_поля").setValue(dto, новое значение);

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

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

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

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

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

В моем случае я пытаюсь издеваться.Класс MessageQueue от Net, чтобы я мог использовать свою логику обработки исключений 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;
    }

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top