Сделать код внутренним, но доступным для модульного тестирования из других проектов - PullRequest
117 голосов
/ 20 сентября 2008

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

Ответы [ 4 ]

185 голосов
/ 20 сентября 2008

Если вы используете .NET, атрибут сборки InternalsVisibleTo позволяет создавать «дружественные» сборки. Это конкретные строго именованные сборки, которым разрешен доступ к внутренним классам и членам другой сборки.

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

Пример:

[assembly: InternalsVisibleTo("NameAssemblyYouWantToPermitAccess")]
namespace NameOfYourNameSpace
{
6 голосов
/ 20 сентября 2008

Если это внутренний класс, то он не должен использоваться изолированно. Поэтому вам не следует тестировать его отдельно от тестирования какого-либо другого класса, который использует этот объект для внутреннего использования.

Так же, как вы не должны тестировать закрытые члены класса, вы не должны тестировать внутренние классы DLL. Эти классы являются деталями реализации некоторого общедоступного класса и поэтому должны быть хорошо реализованы с помощью других модульных тестов.

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

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

3 голосов
/ 23 июня 2012

для документации

в качестве альтернативы вы можете создать экземпляр внутреннего класса с помощью Type.GetType метода

Пример

//IServiceWrapper is public class which is 
//the same assembly with the internal class 
var asm = typeof(IServiceWrapper).Assembly;
//Namespace.ServiceWrapper is internal
var type = asm.GetType("Namespace.ServiceWrapper");
return (IServiceWrapper<T>)Activator
    .CreateInstance(type, new object[1] { /*constructor parameter*/ });

для универсального типа есть другой процесс, как показано ниже:

var asm = typeof(IServiceWrapper).Assembly;
//note the name Namespace.ServiceWrapper`1
//this is for calling Namespace.ServiceWrapper<>
var type = asm.GetType("Namespace.ServiceWrapper`1");
var genType = type.MakeGenericType(new Type[1] { typeof(T) });
return (IServiceWrapper<T>)Activator
     .CreateInstance(genType, new object[1] { /*constructor parameter*/});
0 голосов
/ 20 сентября 2008

Классы могут быть как общедоступными, так и закрытыми.

Но не делай этого.

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

Редактировать: я имею в виду, если вы не хотите включать -any- тестирование в свою оригинальную сборку; это также работает, если члены являются частными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...