В общем, я разрабатываю классы таким образом, чтобы не требовать доступа к рядовым для целей тестирования. Также может помочь 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);
(Да, изобилует антипаттернами, но, пожалуйста, не стреляйте в посланника)
У меня с этим ряд проблем:
- Я хотел бы уточнить, какие из моих частных лиц мне нужны
- Я бы предпочел не вызывать диалоги (да, я CRaholic)
- Я бы предпочел не задействовать генерацию кода на картинке
Поэтому я хотел бы иметь возможность преобразовать приведенный выше код во что-то вроде:
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; Открыт для использования любой динамической прокси-библиотеки или другой