Подтвердить что ты не робот

Доступ к внутренним членам через System.Reflection?

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

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 и очень люблю его, но как я могу достичь с ним того же?

4b9b3361

Ответ 1

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

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

Чтобы ответить на ваш вопрос... Внутренние и защищенные не распознаются в .NET Reflection API. Вот цитата из MSDN:

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

Ответ 2

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

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

[assembly: InternalsVisibleTo("AssemblyB")]

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

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

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

Ответ 3

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

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

работ:

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

Ответ 4

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

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

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

Ответ 5

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

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

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