Мы помещаем все наши модульные тесты в свои собственные проекты. Мы обнаруживаем, что мы должны сделать определенные классы общедоступными, а не только для модульных тестов. В любом случае, чтобы избежать этого. Каковы последствия памяти, делая классы общедоступными, а не запечатанными?
Создание внутреннего кода, но доступного для модульного тестирования из других проектов
Ответ 1
Если вы используете .NET, атрибут InternalsVisibleTo позволяет создавать сборки "друг". Это конкретные узлы с узкими именами, которым разрешен доступ к внутренним классам и членам другой сборки.
Примечание. Это следует использовать с усмотрением, поскольку оно плотно соединяет задействованные сборки. Обычное использование для InternalsVisibleTo для проектов модульного тестирования. Это, вероятно, не очень хороший выбор для использования в ваших реальных сборках приложений по указанной выше причине.
Ответ 2
Если это внутренний класс, он не должен использоваться отдельно. Поэтому вы не должны тестировать его отдельно от тестирования другого класса, который использует этот объект внутри.
Так же, как вы не должны тестировать частных членов класса, вы не должны тестировать внутренние классы DLL. Эти классы являются деталями реализации некоторого общедоступного класса и поэтому должны быть хорошо реализованы с помощью других модульных тестов.
Идея состоит в том, что вы хотите протестировать поведение класса, потому что если вы проверите внутренние детали реализации, ваши тесты будут хрупкими. Вы должны иметь возможность изменять детали реализации любого класса, не нарушая все ваши тесты.
Если вы обнаружите, что вам действительно нужно протестировать этот класс, вам может потребоваться пересмотреть, почему этот класс является внутренним.
Ответ 3
для целей документации
альтернативно вы можете создать экземпляр внутреннего класса с помощью метода 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*/});
Ответ 4
Классы могут быть как общедоступными, так и закрытыми.
Но не делайте этого.
Вы можете создать инструмент, чтобы отражать внутренние классы, и испускать новый класс, который обращается ко всему через отражение. MSTest делает это.
Изменить: Я имею в виду, если вы не хотите включать в свою оригинальную сборку -аниверсифицирующие материалы; это также работает, если члены являются частными.