2008-10-05 2 views
24

Я пытаюсь выполнить Unit Test класса, который имеет много внутренних функций. Они, очевидно, тоже нуждаются в тестировании, но мой проект «Тесты» является отдельным, главным образом потому, что он охватывает многие небольшие связанные проекты. То, что я до сих пор:Доступ к внутренним элементам через System.Reflection?

FieldInfo[] _fields = 
    typeof(ButtonedForm.TitleButton).GetFields(
     BindingFlags.NonPublic | BindingFlags.Instance | 
     BindingFlags.DeclaredOnly); 
Console.WriteLine("{0} fields:", _fields.Length); 
foreach (FieldInfo fi in _fields) 
{ 
    Console.WriteLine(fi.Name); 
} 

Это выплевывает все частные члены красиво, но по-прежнему не отображается внутренностей. Я знаю, что это возможно, потому что, когда я возился с автогенерируемыми тестами, которые Visual Studio может произвести, он спрашивал, что-то делать с отображением внутренних компонентов в проекте Test. Ну, теперь я использую NUnit и очень люблю его, но как я могу добиться того же?

ответ

32

Было бы более целесообразным использовать атрибут InternalsVisibleTo, чтобы предоставить доступ к внутренним элементам сборки к модульной тестовой сборке.

Вот ссылка с некоторой полезной дополнительной информацией и прогулка по:

На самом деле ответить на ваш вопрос ... Внутренний и защищенный не распознается в .NET Reflection API. Вот цитата из MSDN:

C# ключевых слова защищены и внутренние не имеют никакого значения в IL и не используется в API, Reflection. Соответствующие термины в IL - это Семья и Ассамблея. Чтобы идентифицировать внутренний метод с использованием Reflection, используйте свойство IsAssembly. Чтобы определить защищенный внутренний метод, используйте IsFamilyOrAssembly.

+0

Я согласен с использованием InternalsVisibleTo, но спасибо за ответ тоже :) – 2008-10-05 02:05:43

+0

Нет проблем, хорошо иметь фактическое объяснение, даже если в вашем конкретном случае лучше подходит другой подход. – 2008-10-05 02:16:39

+2

Просто FYI, страница, связанная с этим ответом, принадлежит мне, и мой URL-адрес изменился. Вот почему вы можете получить 404. Попробуйте эту обновленную ссылку http://jason.whitehorn.ws/2007/11/09/The-Wonders-Of-InternalsVisibleTo.aspx – 2008-11-23 00:57:00

6

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

Например добавьте следующую строку в сборку за пределами любого класса:

[assembly: InternalsVisibleTo("AssemblyB")] 

Или для более точного таргетинга:

[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")] 

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

6

Я думаю, вам нужно спросить, следует ли вам писать модульные тесты для частных методов? Если вы пишете модульные тесты для ваших общедоступных методов с «разумным» охватом кода, разве вы уже не тестируете какие-либо частные методы, которые нужно назвать результатом?

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

Refs:

http://weblogs.asp.net/tgraham/archive/2003/12/31/46984.aspx http://richardsbraindump.blogspot.com/2008/08/should-i-unit-test-private-methods.html http://junit.sourceforge.net/doc/faq/faq.htm#tests_11 http://geekswithblogs.net/geekusconlivus/archive/2006/07/13/85088.aspx

6

Ваш код только с указанием полей - так что я надеюсь, что не будет показывать любые внутренние элементы, так как поля всегда должны быть частными ИМО. (С потенциальным исключением констант.)

Есть ли ButtonedForm.TitleButton на самом деле какие-либо не-частные поля? Если вы пытаетесь найти внутренние методы , то, очевидно, вам нужно позвонить GetMethods (или GetMembers), чтобы добраться до них.

Как и другие, InternalsVisibleTo очень удобен для тестирования (и почти исключительно для тестирования!). Что касается того, нужно ли тестировать внутренние методы - я, конечно, считаю полезным, чтобы это можно было сделать. Я не рассматриваю модульное тестирование как исключительно тестирование черного ящика. Часто, когда вы знаете, что публичная функциональность реализована с использованием нескольких внутренних методов, связанных простым способом, проще провести тщательное тестирование каждого из внутренних методов и некоторых «псевдоинтеграционных» тестов для общедоступного метода.

1

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

Это идеальный случай, когда имеет смысл InternalsVisible.

Мне было интересно, но чем вы занимаетесь, если у вас нет доступа к источнику? Как вы могли добраться до внутреннего поля? .Net Reflector может видеть этот код, но я думаю, он просто смотрит на IL.

Смежные вопросы