Прокладка пересылки без создания кода для тестирования частных методов

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

Однако в настоящее время я имею дело с кодовой базой, в которой есть несколько областей, которые стали полагаться на [механизм частных средств доступа в VSTS] (http://msdn.microsoft.com/en-us/library/ms184807(VS.80).aspx) (т. е. используя VSCodeGenAccessors для создания *_Accessor классов, которые имеют пересылку, использующую отражение для вызова private членов (и, возможно, internal тоже) в классе.

Итак, у меня есть такой код:

ClassUnderTest target = new ClassUnderTest();
var accessor = ClassUnderTest_Accessor.AttachShadow( target );
accessor.PrivateMethod();
Assert.True( accessor._privateMethodWasCalled);
accessor.PrivateProperty = 5;
Assert.Equal( accessor.PrivateProperty, 5);

(Да, изобилует антипаттернами, но, пожалуйста, не стреляйте в посланника)

У меня с этим ряд проблем:

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

Поэтому я хотел бы иметь возможность преобразовать приведенный выше код во что-то вроде:

var target = new ClassUnderTest();
IClassUnderTestInterface accessor = Shadow.Create<IClassUnderTestInterface>( target );
accessor.PrivateMethod();
Assert.True( accessor._privateMethodWasCalled);
accessor.PrivateProperty = 5;
Assert.Equal( accessor.PrivateProperty, 5);

В моей тестовой сборке находится только следующий интерфейс и нет сгенерированного кода или настраиваемых шагов сборки: -

interface IClassUnderTestInterface
{
   int PrivateProperty {get; set;}
   bool _privateMethodWasCalled {get; }
   void PrivateMethod();
}

Оттуда я мог бы использовать CodeRush или Ctrl K M для создания новых теневых методов в интерфейсе одним нажатием клавиши.

Недостающий бит будет иметь метод I Shadow.Create<I>( Object o), который 1. генерирует динамический прокси, реализующий интерфейс 1. проверяет, что объект o, который должен быть упакован, имеет все элементы, продиктованные интерфейсом 1. bnous: управлять пересылкой свойств, представляющих поля (т.е. случай `_privateMethodWasCalled ') правильно

Итак, кто-нибудь знает библиотеку, которая реализует что-то подобное (или ему достаточно скучно, чтобы писать это?)

Один очевидный недостаток заключается в том, что вы не знаете, несовместим ли интерфейс с ClassUnderTest до времени выполнения, но это нормально, поскольку это будет только для тестов. Также AIUI, механизм частных аксессоров, также требует запуска перекомпиляции для синхронизации времени от времени.

Или есть способ лучше, который мне не хватает? (Помня, что я не хочу уклоняться от унижения частных лиц до внутренних или публичных и не хочу переписывать рабочий код)

Использование xUnit.net, .NET 3.5; Открыт для использования любой динамической прокси-библиотеки или другой


person Ruben Bartelink    schedule 25.06.2009    source источник


Ответы (3)


Вы когда-нибудь видели фреймворки для фиксации, такие как Moq или Rhino? В вашем случае они могут помочь, ЕСЛИ вы захотите изменить частные лица, которые вам нужно протестировать, на «защищенные виртуальные» (что не так уж плохо, если вы публично или внутренне). По сути, если член виртуальный, то фреймворк может сгенерировать подкласс, который записывает, какие члены вызываются.

person Sylvain    schedule 26.06.2009
comment
Интересная идея. Вопрос о том, лучше ли сделать что-то защищенное для облегчения тестирования, чем сделать это внутренним, хотя ИМО ... Но виртуальный возможен и может помочь в реализации (конечно, через LazyWeb). Спасибо за идею. (Из +1 за день, но со временем появится один!) - person Ruben Bartelink; 26.06.2009
comment
Конечно, ключевым моментом является то, что я в значительной степени ищу здесь реализацию .... - person Ruben Bartelink; 29.06.2009

В итоге я обошел весь этот материал (InternalsVisibleTo, отдельные тестовые проекты, ссылки на тесты, частные средства доступа, случайный сбой задачи MSBuild Shadow / publicize.exe в сборках, используя отражение для доступа к частным объектам) путем объединения тестов в основные проекты и создания все, что нужно было получить из тестов internal). См. Также xUnit. net Test Stripper [для удаления тестового кода, встроенного в двоичные файлы, перед развертыванием / доставкой]

person Ruben Bartelink    schedule 26.11.2009
comment
github.com/markrendle/Trespasser/tree/master/Trespasser Похоже это просто работа, но я не могу сейчас ее опробовать - person Ruben Bartelink; 29.11.2010
comment
Через @ajasinski был более ранний igoro.com/archive/ (но Trespasser выглядит нормально и находится на NuGet) - person Ruben Bartelink; 11.04.2013

Этот хитрый трюк, который может сделать функции пересылки более краткими , хотя это все еще ручной характер

Кроме того, этот ответ описывает, как обрабатывать static членов (но требует CLR4, который не был задействован на момент моего запроса и не обрабатывает частные методы, не добавляя InternalsVisibleTo в микс).

person Ruben Bartelink    schedule 12.02.2010