Внутрішні методи тестування модулів у бібліотеці VS2017 .Net Standard


150

В даний час я граю з останнім кандидатом випуску Visual Studio 2017, створивши бібліотеку .Net Standard 1.6. Я використовую xUnit для тестування свого коду, і мені було цікаво, чи можна ще перевірити внутрішні методи у VS2017.

Я пам’ятаю, що ви могли всі рядки клас AssemblyInfo.cs у VS2015, які б давали змогу вказаним проектам бачити внутрішні методи

[assembly:InternalsVisibleTo("MyTests")]

Оскільки у VS2017 немає класу AssemblyInfo.cs, мені було цікаво, чи можна все-таки використовувати внутрішні методи тестування?


3
Ви повинні мати можливість перевірити свій код лише на зовнішньо видимих ​​функціональних можливостях. Зрештою, якщо жоден логічний шлях із зовнішнього коду не може досягти цих внутрішніх методів, то що б вони там робили в першу чергу?
Девід

3
@David Я можу і зробив це, але раніше я поставив прості одиничні тести навколо деяких внутрішніх класів. Просто, щоб бути більш чітким у тестуванні.
Філ Мюррей

5
AFAIK, ви можете розмістити цей атрибут у будь-якому іншому файлі, поза namespaceблоком, і він повинен компілюватись. Не повинно бути нічого магічного AssemblyInfo.cs. Це не працює? Звичайно, потрібно додати правильний usingпункт або використовувати повністю кваліфікований атрибут [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Something")].
Груо

1
@David Якщо ви створюєте бібліотеку з внутрішніми класами і вам необхідно перевірити і знущатися ці класи, InternalsVisibleToмає вирішальне значення - наприклад , тут - stackoverflow.com/a/17574183/43453
PandaWood

Відповіді:


210

Згідно з документами .NET дляInternalsVisibleToAttribute :

Атрибут застосовується на рівні складання. Це означає, що він може бути включений на початку файлу вихідного коду, або він може бути включений у файл AssemblyInfo у проекті Visual Studio.

Іншими словами, ви можете просто розмістити його у власному довільному файлі .cs, і він повинен працювати добре:

// some .cs file included in your project
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]

1
@PhilMurray: також, мабуть, існує налаштування, яка б дозволила вам створити "класичний" AssemblyInfo.csфайл, як пояснено тут . В іншому випадку всі атрибути, такі як "опис", "авторське право" та інші речі, зберігаються у файлі .csproj.
Груо

43

Як описано тут:

https://blog.sanderaernouts.com/make-internals-visible-with-new-csproj-format

Можна додати внутрішній видимий атрибут до файлу проекту, додавши ще один ItemGroup:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(AssemblyName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

або навіть:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

Мені подобається це рішення, тому що файл проекту, здається, є правильним місцем для визначення таких проблем.


8

Хоча перша відповідь ідеально чудова. Якщо ви відчуваєте, що все ще хочете зробити це в оригіналі, AssemblyInfoви завжди можете вирішити не автоматично генерувати файл, а додати його вручну.

<PropertyGroup>
   <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

Для отримання додаткової інформації: https://stackoverflow.com/a/47075759/869033


5

Атрибут "InternalsVisibleTo" є ключовим для будь-якого тестування "білого поля" (термін десятиліття, я думаю) для .Net. Його можна розмістити у будь-якому файлі c # з атрибутом "збирання" на передній панелі. Зауважте, що MS DOC кажуть, що ім'я складання повинно кваліфікуватися за допомогою маркера відкритого ключа, якщо він підписаний. Іноді це не працює, і потрібно використовувати повний відкритий ключ на своєму місці. Доступ до внутрішніх справ є ключовим для тестування паралельних систем та у багатьох інших ситуаціях. Дивіться https://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 . У цій книзі Месзарос описує різноманітні стилі кодування, які в основному складають підхід "Design For Test" до розробки програми. Принаймні, так я використовував її протягом багатьох років.

ДОБАВЛЕНО: Вибачте, я не був тут деякий час. Один із підходів називає підхід "тестування підкласу" Медзаросом. Знову ж таки, потрібно використовувати "Internalsvisableto" для доступу до внутрішніх даних базового класу. Це чудове рішення, але воно не працює для закритих класів. Коли я викладаю "Дизайн для тесту", я припускаю, що це одна з речей, яку потрібно зробити заздалегідь розробленими в базові класи, щоб забезпечити перевірку. Це має стати майже культурною річчю. Сконструюйте базовий клас, який не є герметичним. Назвіть це UnsealedBaseClass або щось рівнозначне. Це клас, який слід підкласифікувати для тестування. Крім того, підклас складається для виготовлення виготовленого герметичного класу, який часто відрізняється лише конструкторами, які він виставляє. Я працюю в ядерній промисловості, і вимоги до випробувань дуже серйозно сприймаються. Отже, я повинен постійно думати про ці речі. До речі, залишення тестових гаків у виробничому коді не вважається проблемою в нашій галузі, якщо вони є "внутрішніми" в реалізації .Net. Наслідки НЕ тестування чогось можуть бути досить глибокими.


1

Інший спосіб - використовувати публічний клас "обгортки" TestMyFoo у цільовому проекті, який має публічні методи та нікуди від класу, який потрібно перевірити (наприклад, MyFoo). Ці загальнодоступні методи просто викликають базовий клас, який ви хочете протестувати.

Це не "ідеально", оскільки ви в кінцевому підсумку відправляєте тестовий гачок у своєму цільовому проекті. Але розглянемо сучасні надійні автомобілі, що поставляються з діагностичними портами, і сучасні надійні електронні кораблі з підключенням JTAG. Але ніхто не є дурним, щоб керувати автомобілем, використовуючи діагностичний порт.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.