Когда я пишу тесты для определенных типов объектов, таких как элементы пользовательского интерфейса, такие как Forms или UserControls, я часто изменяю свой шаблон TDD; вместо того, чтобы идти сначала в тест, я определяю и размечаю элементы управления формы, чтобы обеспечить «скелет», затем начинаю писать поведенческие тесты (привязка данных / «открепление», поведение в режиме отображения и т. д.). При этом я сталкиваюсь с непубличными членами. Я также сталкиваюсь с той же проблемой с другими поведенческими методами; Я могу захотеть сосредоточиться и использовать логику в каком-то частном помощнике, вызываемом другим методом, прежде чем беспокоиться об использовании другого метода и его поведении.
Для меня, сделать все публичным (а иногда и виртуальным) просто для того, чтобы можно было все протестировать, - это запах; Я не хочу, чтобы другие объекты могли вызывать помощника или напрямую получать доступ к текстовому полю; но мне нужно знать, что помощник выполняет свою работу, и текстовое поле получает свое значение при загрузке формы.
Решение, которое я получил некоторое время назад, заключается в создании «тестового прокси» для реального тестируемого объекта. Прокси-сервер является производным от тестируемого объекта и не скрывает и не переопределяет какое-либо поведение, но он предоставляет внутренне видимые методы получения, установки и / или методы, которые делают вызовы непубличным членам тестируемого объекта, что позволяет мне попросите объект выполнить определенные действия, из которых я могу затем просмотреть результаты, не требуя, чтобы тест также зависел от правильной интеграции в объекте или от того, что метод или какой-либо другой представляющий интерес элемент публикуется в производственном коде только для целей тестирования.
Преимущества, которые я вижу:
- Видимость членов не определяется тем, хотите ли вы модульный тест или нет.
- Более точный контроль над тем, что вы можете делать с объектом в тесте, позволяет проводить более гибкое и расширяемое тестирование.
Недостатки, которые я вижу:
- Количество классов увеличивается, с дополнительным уровнем для разработки только для целей тестирования.
- Необходимо позаботиться о том, чтобы каким-то образом не использовать тестовый прокси в производственном коде (обычно это делает конструктор или весь внутренний класс)
- Не «чистый» модульный тест, поскольку на некотором уровне вы зависите от интеграции между прокси-сервером и реальным тестируемым объектом.
Вопрос в том, является ли это правильным способом создания модульных тестов, или тот факт, что я должен сделать это, указывает на проблему с кодом или стратегией тестирования?