Как разрешить сборке (модульному тестированию один) доступ к внутренним свойствам другой сборки?

Я хотел бы, чтобы моя сборка Core не выставляла определенный класс, и я все еще хотел бы иметь возможность протестировать его. Как я могу это сделать?

7 ответов

Решение

Атрибут InternalsVisibleTo для спасения!

Просто добавь:

[assembly:InternalsVisibleToAttribute("UnitTestAssemblyName")]

в ваш файл AssemblyInfo.cs классов Core

См. Сборки друзей (Руководство по программированию в C#) для получения информации о передовых методах.

С InternalsVisible, если ваши сборки имеют строгое имя, вам нужно указать открытый ключ (примечание: полный ключ, а не токен открытого ключа), например...

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("BoardEx_BusinessObjects.Tests, 
  PublicKey=0024000004800000940000000602000000240000525341310004000001000100fb3a2d8 etc etc")]

и следующий трюк действительно полезен для получения открытого ключа без обращения к строке cmd...

http://www.andrewconnell.com/blog/archive/2006/09/15/4587.aspx

Я поместил свои модульные тесты в ту же сборку, что и код, который они тестируют. Это имеет смысл для меня, потому что я считаю "проверить себя" как особенность класса, наряду с такими вещами, как "инициализировать себя" и "описать себя".

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

Повреждает производительность Бах, говорю! Не оптимизируйте без точных данных! Возможно, если вы планируете загружать сборки по медленным ссылкам, то минимизировать размер сборки будет целесообразно.

Это риск для безопасности. Только если у вас есть секреты в ваших тестах. Не делай этого.

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

В стороне: в C# я однажды попытался поместить свои модульные тесты в класс с именем "Tests", который был вложен в класс, который он тестировал. Это сделало правильную организацию вещей очевидной. Это также позволило избежать дублирования имен, возникающего, когда тесты для класса "Foo" находятся в классе с именем "FooTests". Однако рамки модульного тестирования, к которым я имел доступ, отказывались принимать тесты, которые не были помечены как "публичные". Это означает, что класс, который вы тестируете, не может быть "закрытым". Я не могу придумать какой-либо веской причины требовать, чтобы тесты были "общедоступными", поскольку никто не называет их публичными методами - все через отражение. Если вы когда-нибудь напишете фреймворк модульного тестирования для.Net, пожалуйста, подумайте о том, чтобы разрешить закрытые тесты, ради меня!

Я бы посоветовал не идти на такие неприятности... если вы действительно хотите провести модульное тестирование своих "внутренних" классов, просто спрячьте их в пространстве имен, которое будет использовать только ваш внутренний код. Если вы не пишете фреймворк в масштабе.NET, вам не нужен этот уровень сокрытия.

Вы можете использовать отражение (как это делают элементы MS Test), или вы можете объявить сборку модульного теста другом сборки ядра.

Другой вариант - поместить модульные тесты в одну сборку.

Начнем с примера класса:

      using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("App.Infrastructure.UnitTests")]

namespace App.Infrastructure.Data.Repositories
{
    internal class UserRepository : IUserRepository
    {
        // internal members that you want to test/access
    }
}

В Атрибут позволяет другой сборке получить доступ ко всем вашим внутренним классам и членам , но атрибут InternalsVisibleTo применяется не только к одному классу (в том месте, где вы его объявили), а ко ВСЕЙ сборке.

В примере кода - может получить доступ ко всем внутренним компонентам в объявленной вами сборке (атрибут InternalsVisibleTo), даже если вы не объявили ее явно для других классов, принадлежащих к той же сборке.


есть 2 подхода к тому, чтобы сделать ваши внутренние компоненты доступными для определенных сборок (или сборок) .

1. Создание собственного файла AssemblyInfo.cs

Это единственные строки, которые вам понадобятся в файле AssemblyInfo.cs (удалите весь код «по умолчанию» и замените его кодом ниже)

      using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("App.Infrastructure.UnitTests"),
           InternalsVisibleTo("Another.Assembly")]

2. Добавление атрибута InternalsVisibleTo в файл проекта .csproj (дважды щелкните проект, внутренние компоненты которого вы хотите открыть)

      <ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>The_Assembly_That_Can_Access_Your_Internals</_Parameter1>
    </AssemblyAttribute>
    
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>Another_Assembly_Or_Project</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

Примечание. В этом видео на YouTube я узнал:Посмотрите полное видео на YouTube для более подробного объяснения атрибутов уровня сборки .

в ядре dotnet мы можем добавить AssembyAttribute в файл .csproj

просто добавьте это в свой .csproj

      <!-- Make internals available for Unit Testing -->
<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>Myproject.Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>
<!-- End Unit test Internals -->
Другие вопросы по тегам